-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
Initial commit
0 parents
commit daad758
Showing
14 changed files
with
824 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
name: Build Docs | ||
|
||
on: | ||
workflow_dispatch: | ||
repository_dispatch: | ||
types: [update_data] | ||
push: | ||
paths: | ||
- "_includes/**" | ||
- "_layouts/**" | ||
|
||
permissions: | ||
contents: read | ||
pages: write | ||
id-token: write | ||
|
||
concurrency: | ||
group: "pages" | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: read | ||
issues: write | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
- run: ./scripts/build-data.sh --remote | ||
- name: Set up Ruby | ||
uses: ruby/setup-ruby@v1 | ||
with: | ||
ruby-version: "2.7.1" | ||
bundler-cache: true | ||
- name: Build with Jekyll | ||
run: bundle exec jekyll build | ||
- name: Upload artifact | ||
uses: actions/upload-pages-artifact@v3 | ||
# Deployment job | ||
deploy: | ||
environment: | ||
name: github-pages | ||
url: ${{ steps.deployment.outputs.page_url }} | ||
runs-on: ubuntu-latest | ||
needs: build | ||
steps: | ||
- name: Deploy to GitHub Pages | ||
id: deployment | ||
uses: actions/deploy-pages@v4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
source 'https://rubygems.org' | ||
|
||
gem 'jekyll' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# what i'm reading | ||
|
||
```sh | ||
./scripts/build-data.sh --out _data2 | ||
./scripts/build-data.sh --remote | ||
``` | ||
|
||
```sh | ||
bundle install | ||
bundle exec jekyll build | ||
bundle exec jekyll serve | ||
``` | ||
|
||
# trigger update | ||
|
||
``` | ||
curl -H "Accept: application/vnd.github.everest-preview+json" \ | ||
-H "Authorization: token ${GITHUB_TOKEN}" \ | ||
--request POST --data '{"event_type": "update_data"}' \ | ||
https://api.github.com/repos/nntrn/what-im-reading/dispatches | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
title: what i'm reading | ||
description: Bookmarks from Apple Books | ||
author: Annie Tran | ||
url: https://nntrn.github.io | ||
baseurl: /what-im-reading | ||
repository: nntrn/what-im-reading | ||
github_username: nntrn | ||
favicon_ico: /assets/favicon.ico | ||
|
||
kramdown: | ||
smart_quotes: ["apos", "apos", "quot", "quot"] | ||
|
||
compress_html: | ||
clippings: [div, p, ul, td, h1, h2] | ||
endings: all | ||
comments: ["<!--", "-->"] | ||
startings: [] | ||
blanklines: true | ||
profile: false | ||
|
||
page_gen: | ||
- data: "genre" | ||
template: "genre" | ||
index_files: true | ||
dir: "tag" | ||
- data: "books" | ||
template: "book" | ||
name: "slug" | ||
index_files: false | ||
dir: "tags" | ||
|
||
exclude: | ||
- README.md | ||
- Gemfile.lock | ||
- .archive | ||
- annotations.json | ||
- scripts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
function highlightAnnotation() { | ||
Array.from(document.querySelectorAll('.mark')).forEach(e => e.classList.remove('mark')) | ||
if (Number(location.hash.substr(1,))) { | ||
document.querySelector(`.bookmark a[href="${location.hash}"]`).parentElement.parentElement.classList.add('mark') | ||
} | ||
} | ||
highlightAnnotation() | ||
window.onhashchange = highlightAnnotation; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
:root{--px-size:2.5%;--progress-size:13px} | ||
*{box-sizing:border-box} | ||
html{font-size:12px} | ||
.h100,body,html,main{height:100%} | ||
body{font-variant:proportional-width;display:flex;flex-direction:column;gap:.25rem;scrollbar-width:thin;margin:0 0;padding:0 0;margin:auto;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-size:inherit;line-height:1.25;counter-reset:reversed(section);text-rendering:optimizeLegibility;overflow-y:hidden} | ||
br{line-height:0!important;font-size:0!important} | ||
date{margin-right:.5rem;text-transform:uppercase} | ||
header{padding:.85rem 0;position:sticky;top:0;z-index:100;background:#fff;border-bottom:1px solid #ccc} | ||
footer{margin-top:1rem} | ||
header h1{padding-left:var(--px-size);padding-right:var(--px-size)} | ||
footer p{border-top:1px solid #aaa;padding-top:1rem;text-align:right} | ||
main{gap:2rem;position:relative;padding-left:var(--px-size);padding-right:var(--px-size);width:100%;scrollbar-width:thin;overflow-y:scroll;margin-bottom:0;display:block;padding:calc(1rem/2) var(--px-size);height:100%;display:flex;flex-direction:column;justify-content:space-between} | ||
a{color:#36c} | ||
a:empty{text-decoration:none;color:inherit} | ||
a:empty:after{content:attr(href)} | ||
a:hover{text-decoration-color:#36c} | ||
a{text-decoration:1.25px underline;text-decoration-skip-ink:none;text-underline-offset:1px;text-rendering:geometricprecision;color:#36c;text-decoration-color:#3366cc61} | ||
aside .container{border-right:1px dotted #222;min-height:75vh} | ||
aside{flex:1;min-width:25vw;position:relative} | ||
aside a,aside u{text-underline-offset:1.25px;text-decoration-skip-ink:none;text-decoration-thickness:1.2px} | ||
aside a:hover{color:#222;text-decoration-color:#aaa} | ||
aside h4 a{font-family:sans-serif;font-size:.9em} | ||
aside strong{font-weight:700;display:block;line-height:1.1} | ||
h1,h2,h4{margin:0 0} | ||
h3{margin:.5rem 0} | ||
h1 a{color:#222} | ||
h1,h2,h3{font-family:times} | ||
h3 a{text-transform:capitalize;text-decoration:none;color:initial;font-size:1.3rem} | ||
hr{border:0;border-bottom:1px solid #aaa;margin:1rem 0} | ||
label span:empty{display:none} | ||
ul.list{padding:0 0rem;list-style:none;padding-right:1rem} | ||
ol,ul{display:flex;flex-direction:column;gap:.5rem;padding:0 2rem;padding-right:1rem} | ||
ul>li{padding:0 .4rem} | ||
ol,ul{padding:0 1.35rem} | ||
ol{padding-left:0} | ||
ol li{list-style:none;padding-left:0} | ||
q:after,q:before{content:""} | ||
q{white-space:pre-wrap} | ||
section{flex:10} | ||
small a{color:inherit;text-decoration:inherit} | ||
small a:hover{opacity:.75} | ||
table{line-height:1.3;border-collapse:collapse} | ||
tr>*{padding-bottom:.5rem;padding-top:.5rem} | ||
td,th{vertical-align:top} | ||
td label{font-size:.9em} | ||
th date{white-space:pre;font-weight:400;color:#8e8e8e} | ||
th{border-right:1.5px dotted #222} | ||
th[data-level="1"]{text-align:right;border:0;font-size:1.4em;white-space:pre;transition:all .6s linear;max-width:min-content} | ||
th[data-level="2"]{text-align:right} | ||
td[colspan]{padding-left:11%} | ||
tr{line-height:1.2} | ||
.right{text-align:right} | ||
mark{background:0 0} | ||
mark strong{color:#fff;background:#222;padding:0 2px} | ||
mark strong{font-size:.9rem} | ||
[colspan] h2{padding-top:1.5rem} | ||
.bookmark .meta{font-size:.9rem;color:#aaa;text-transform:uppercase;font-variant:proportional-nums} | ||
.bookmark a{text-decoration:none} | ||
.bookmark{padding:0 .5rem} | ||
.bold{font-weight:700} | ||
.normal{font-weight:400} | ||
.small{font-size:.8rem} | ||
.col{flex-direction:column} | ||
.content{flex:3} | ||
.content a:hover{text-decoration:underline} | ||
.content a{text-decoration:none} | ||
.content h2{line-height:1} | ||
.content li>a:hover{color:#222} | ||
.content li>a{transition:all 0s;color:#aaa;font-family:sans-serif;text-transform:uppercase;font-variant:proportional-nums} | ||
.content p time{font-weight:700} | ||
.content span{white-space:pre-wrap} | ||
.content ul{gap:1rem} | ||
.flex{display:flex} | ||
.fw-500{font-weight:400!important} | ||
.header a{color:inherit;text-decoration:none;text-transform:capitalize} | ||
.header>*{margin:0 0;padding:0 0} | ||
.gap{gap:var(--gap,.25rem)} | ||
.list>li{padding:0 0} | ||
.mark q{background:#fff0b1;line-height:1.4} | ||
.meta a:hover{text-decoration:none;color:#a7a7a7} | ||
.meta a{color:#000;font-weight:700} | ||
.meta{margin-top:.25rem} | ||
.padded{padding-left:.75rem;padding-right:.75rem} | ||
.chapters{flex:1} | ||
.toc{max-height:min(300px,40vh);position:sticky;top:0;list-style:none;padding:0 0;margin:0 0;z-index:1;width:20px;max-width:20px} | ||
.toc div{padding:0 0;font-size:.9em;position:relative} | ||
.toc a:hover:before{content:attr(title);position:absolute;right:20px;background:#222;padding:4px 4px;color:#fff;z-index:1;font-size:.9em} | ||
.toc a{color:#222;white-space:pre;text-align:center;padding:0 4px;line-height:1} | ||
.toc a:hover{text-decoration:none;font-weight:700} | ||
.toc a:before{font-weight:500} | ||
.site-title a{text-decoration-color:rgba(0,0,0,.1);text-underline-offset:2px;text-decoration-thickness:1.75px;font-family:times;font-weight:700;font-size:.9em;text-decoration-skip-ink:all} | ||
[id]>a:hover:after{content:"#";color:#aaa} | ||
aside ul{display:inline-flex;gap:.1rem;position:relative;position:sticky;top:0} | ||
@media (max-width:750px){ | ||
aside .container{min-height:20vh} | ||
main>.flex{display:flex;flex-direction:column-reverse} | ||
:root{--px-size:1rem} | ||
aside ul{margin:1rem .5rem} | ||
ol{padding:0 2.5rem} | ||
ol li{list-style:unset;padding-left:unset} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
--- | ||
layout: default | ||
type: book | ||
--- | ||
{%- assign pagecreated = page.created | date_to_string: "ordinal", "US" %} | ||
{%- assign pagemodified = page.modified | date_to_string: "ordinal", "US" -%} | ||
{%- assign annotations = site.data.activity | where: 'assetid', page.assetid | sort: "cfi" %} | ||
{%- assign total = annotations.size %} | ||
{%- assign chapters = annotations | group_by: "chapter" %} | ||
<div class="flex gap" style="--gap:2rem"> | ||
{%- include postlist.html %} | ||
<article class="content" style="--total: {{total}}"> | ||
<h2>{{page.title}}</h2> | ||
<h3>{{page.author}}</h3> | ||
<p> | ||
First annotation on <time>{{pagecreated}}</time>.{%- if pagemodified != pagecreated -%} Last on <time>{{pagemodified}}</time>.{%- endif %} | ||
</p> | ||
<p>{{annotations.size}} bookmark{%- if annotations.size > 1 -%}s{%- endif -%}</p> | ||
<hr> | ||
<section class="flex"> | ||
<div class="chapters"> | ||
{%- for chapter in chapters %} | ||
{%- assign sortedchapteritems = chapter.items | sort: "cfi" %} | ||
<h3 id="{{chapter.name | slugify: 'latin'}}">{{chapter.name | replace: "#","" |strip}}</h3> | ||
<ul> | ||
{%- for annotation in sortedchapteritems %} | ||
<li id="{{annotation.id}}" class="bookmark"> | ||
<q>{{annotation.text}}</q> | ||
<br><span class="meta"><a href="#{{annotation.id}}">#{{annotation.id}}</a> • <time>{{annotation.created|date: '%b %-d %Y %-I:%M%p'}}</time></span> | ||
</li> | ||
{%- endfor %} | ||
</ul> | ||
{%- endfor %} | ||
</div> | ||
<div class="toc"> | ||
{%- for chapter in chapters %} | ||
<div style="--length: {{chapter.items|size}}"><a title="{{chapter.name|replace: '#',''|strip}}" href="#{{chapter.name | slugify: 'latin'}}">—</a></div> | ||
{%- endfor %} | ||
</div> | ||
</section> | ||
</article> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"> | ||
<meta charset="UTF-8"> | ||
<title>{{page.title|default:site.title}} | @nntrn</title> | ||
<link rel="canonical" href="{{ page.url | absolute_url }}" /> | ||
<link rel="icon" href="{{site.favicon_ico|relative_url}}" type="image/x-icon"> | ||
<meta name="description" content="{{site.description}}" /> | ||
<meta name="author" content="{{site.author}} (@{{site.github_username}})"> | ||
<meta name="robots" content="index, follow"> | ||
<meta name="mobile-web-app-capable" content="yes"> | ||
<meta name="apple-mobile-web-app-capable" content="yes"> | ||
<meta name="apple-mobile-web-app-status-bar-style" content="default"> | ||
<meta property="og:site_name" content="{{ site.title }}"> | ||
<meta property="og:type" content="website"> | ||
<meta property="og:url" content="{{ page.url | absolute_url }}"> | ||
<meta property="og:title" content="{{ page.title | default: site.title }}"> | ||
<meta property="og:description" content="{{ page.description | default: site.description }}"> | ||
<meta name="twitter:site" content="{{ site.title }}"> | ||
<meta name="twitter:card" content="summary"> | ||
<meta name="twitter:url" content="{{ site.url | absolute_url }}"> | ||
<meta name="twitter:title" content="{{ page.title | default: site.title }}"> | ||
<meta name="twitter:description" content="{{ page.description | default: site.description }}"> | ||
<style> | ||
{% include style.css %} | ||
</style> | ||
</head> | ||
<body> | ||
<header> | ||
<h1 class="site-title"><a href="{{ '/' | relative_url }}">{{site.title}}</a></h1> | ||
</header> | ||
<main> | ||
{{ content }} | ||
<footer> | ||
<p>Created by <a href="https://github.com/{{site.repository}}">@{{site.github_username}}</a></p> | ||
</footer> | ||
</main> | ||
{%- if page.type == "book" %} | ||
<script> | ||
{% include script.js %} | ||
</script> | ||
{%- endif %} | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
--- | ||
layout: default | ||
type: genre | ||
--- | ||
{%- assign title = page.tag -%} | ||
{%- assign pagetag = page.tag -%} | ||
{%- assign bookpages = site.data.books | where: 'tags', pagetag -%} | ||
<section> | ||
<h2>#{{pagetag}}</h2> | ||
<ul style="width:90%"> | ||
{% for book in bookpages -%} | ||
{% assign bookurl = book.tags | join: "/" | join: book.slug %} | ||
<li><a href="{{ book.slug }}">{{book.title}}</a> by {{book.author}}</li> | ||
{% endfor %} | ||
</ul> | ||
</section> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
# coding: utf-8 | ||
# Generate html pages from data in `_data/` and apply layout from `_layouts` | ||
# Adapted from Adolfo Villafiorita and modified by @nntrn (github.com/nntrn) | ||
|
||
module Jekyll | ||
module Sanitizer | ||
def sanitize_filename(name) | ||
if(name.is_a? Integer) | ||
return name.to_s | ||
end | ||
return name.tr( | ||
"ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÑñÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž", | ||
"AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz" | ||
).downcase.strip.gsub(' ', '-').gsub(/[^\w.-]/, '') | ||
end | ||
end | ||
|
||
class DataPage < Page | ||
include Sanitizer | ||
|
||
def initialize(site, base, index_files, dir, page_data_prefix, data, name, name_expr, title, title_expr, template, extension, debug) | ||
@site = site | ||
@base = base | ||
|
||
if name_expr | ||
record = data | ||
raw_filename = eval(name_expr) | ||
if raw_filename == nil | ||
return | ||
end | ||
else | ||
raw_filename = (index_files ? "index" : data[name]) | ||
if raw_filename == nil | ||
return | ||
end | ||
end | ||
if title | ||
raw_title = data[title] | ||
end | ||
|
||
filename = sanitize_filename(raw_filename).to_s | ||
@dir = (data[dir] ? data[dir] : dir) | ||
@name = (index_files ? "index" : filename) + "." + extension.to_s | ||
|
||
self.process(@name) | ||
|
||
if @site.layouts[template].path.end_with? 'html' | ||
@path = @site.layouts[template].path.dup | ||
else | ||
@path = File.join(@site.layouts[template].path, @site.layouts[template].name) | ||
end | ||
|
||
base_path = @site.layouts[template].path | ||
base_path.slice! @site.layouts[template].name | ||
self.read_yaml(base_path, @site.layouts[template].name) | ||
|
||
if page_data_prefix | ||
self.data[page_data_prefix] = data | ||
else | ||
if data.key?('name') | ||
data['_name'] = data['name'] | ||
end | ||
self.data.merge!(data) | ||
end | ||
|
||
end | ||
end | ||
|
||
class JekyllDatapageGenerator < Generator | ||
safe true | ||
|
||
def generate(site) | ||
index_files = site.config['page_gen-dirs'] == true | ||
|
||
data = site.config['page_gen'] | ||
if data | ||
data.each do |data_spec| | ||
index_files_for_this_data = data_spec['index_files'] != nil ? data_spec['index_files'] : index_files | ||
template = data_spec['template'] || data_spec['data'] | ||
name = data_spec['name'] | ||
name_expr = data_spec['name_expr'] | ||
title = data_spec['title'] | ||
title_expr = data_spec['title_expr'] | ||
dir = data_spec['dir'] || data_spec['data'] | ||
extension = data_spec['extension'] || "html" | ||
page_data_prefix = data_spec['page_data_prefix'] | ||
debug = data_spec['debug'] | ||
|
||
if not site.layouts.key? template | ||
puts "error (datapage-gen). could not find template #{template}. Skipping dataset #{name}." | ||
else | ||
records = nil | ||
|
||
data_spec['data'].split('.').each do |level| | ||
if records.nil? | ||
records = site.data[level] | ||
else | ||
records = records[level] | ||
end | ||
end | ||
if (records.kind_of?(Hash)) | ||
records = records.values | ||
end | ||
|
||
records = records.select { |record| record[data_spec['filter']] } if data_spec['filter'] | ||
records = records.select { |record| eval(data_spec['filter_condition']) } if data_spec['filter_condition'] | ||
|
||
records.uniq.each do |record| | ||
site.pages << DataPage.new(site, site.source, index_files_for_this_data, dir, page_data_prefix, record, name, name_expr, title, title_expr, template, extension, debug) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
# module DataPageLinkGenerator | ||
# include Sanitizer | ||
# | ||
# def datapage_url(input, dir) | ||
# extension = @context.registers[:site].config['page_gen-dirs'] ? '.pug' : '.html' | ||
# end | ||
# end | ||
|
||
end | ||
|
||
# Liquid::Template.register_filter(Jekyll::DataPageLinkGenerator) |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
--- | ||
title: what i'm reading | ||
layout: default | ||
--- | ||
{% assign books_by_date = site.data.books | sort: 'created' |reverse | group_by_exp: "item", "item.created | date: '%b %Y'" -%} | ||
<section class="books"> | ||
<table style="--gap:.25rem"> | ||
{%- for books in books_by_date %} | ||
{%- assign list = books.items | sort: 'created' |reverse %} | ||
<tr class="header"> | ||
<th data-level="1"><h2 id="{{books.name| slugify: 'latin'}}">{{books.name| replace: "-", " " |capitalize}}</h2></th> | ||
<td></td> | ||
</tr> | ||
<tr> | ||
<td class="right">started <mark><strong>{{list.size}}</strong> book{% if list.size > 1 %}s{%- endif -%}</mark></td> | ||
<td></td> | ||
</tr> | ||
{%- for book in list %} | ||
{%- assign statcount = site.data.stats.bookmarks_per_month[books.name] %} | ||
<tr data-genre="{{book.tags}}" data-created="{{book.created}}" data-author="{{book.author}}" data-count="{{book.count}}"> | ||
<th scope="col" data-level="2" class="padded"> | ||
<div><time>{{book.created|date: '%F'}}</time></div><div class="small normal"><a href="{{book.tags}}"></a></div> | ||
</th> | ||
<td class="padded"> | ||
<a href="./{{book.tags}}/{{book.slug}}.html"><strong>{{book.title}}</strong></a><br><label>{{book.author}} • {{book.count}}</label> | ||
</td> | ||
</tr> | ||
{%- endfor %} | ||
<tr> | ||
<td></td> | ||
<td>created <mark><strong>{{statcount}}</strong> bookmark{% if statcount > 1 %}s{%- endif -%}</mark></td> | ||
</tr> | ||
<tr><td colspan="2"><br></td></tr> | ||
{%- endfor -%} | ||
</table> | ||
</section> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
def squo: [39]|implode; | ||
def lpad(n): tostring | if (n > length) then ((n - length) * "0") + . else . end; | ||
def squote($text): [squo,$text,squo]|join(""); | ||
def dquote($text): "\"\($text)\""; | ||
|
||
def unsmart: . | gsub("[“”]";"\"") | gsub("[’‘]";"'"); | ||
|
||
def unsmart($text): $text | unsmart; | ||
|
||
def get_tags($tag): ($tag|split("[\\s]?([^\\w\\s]|for)[\\s]";"x")?|max_by(split(" ")|length)|ascii_downcase|gsub("[\\s]";"-";"x")); | ||
|
||
def get_tags: get_tags(.); | ||
|
||
def get_author($a): | ||
(($a|split("(\\s)?[;&,]+";"x")|.[0]|gsub("[':]";"")|gsub("[\\.\\s]+";"-")|ascii_downcase)?); | ||
|
||
def get_author: get_author(.); | ||
|
||
def epublocation($cfi): | ||
$cfi | ||
| gsub("[^0-9]";"-") | gsub("^[-]+";"") | gsub("[-]+$";"";"x") | gsub("[-]{1,}";"-") | ||
| split("-")|.[1:] | ||
| map(select(length < 5)|tonumber); | ||
|
||
def remove_citations($text): | ||
$text | ||
| gsub("(?<a>[^0-9\\$,]{3})[0-9]{1,2}(?<b>[^0-9%\\.,]{2})"; .a +.b; "x") | ||
| gsub("(?<a>[^0-9]{3})[0-9]{1,2}([\\s]+)?$"; .a +.b; "xs"); | ||
|
||
def remove_citations: remove_citations(.); | ||
|
||
def split_long_title($text): | ||
$text | ||
| split("\\s?[(:)]\\s?";"x") | ||
| (map(select(length > 0))| [.[0],(.[1:]|map(select(contains("Volume"))))]|flatten|join(" ")); | ||
|
||
def slugify($text): | ||
([39]|implode) as $squo | ||
| (if ($text|length)>40 then split_long_title($text) else $text end) | ||
| ascii_downcase | ||
| gsub($squo;"";"x") | ||
| gsub("[\\*\"]";"";"x") | ||
| gsub("[^a-zA-Z0-9]+";"-";"x") | ||
| gsub("-$";"";"x"); | ||
|
||
def get_author_slug($s): | ||
$s | ||
| (if test("&";"x") then split("[,&][\\s]?";"x") else split("; ") end )[0] | ||
| gsub("[.,]";"") | ||
| gsub("[^\\w\\d]+";"-";"x") | ||
| gsub("-$";"";"x") | ||
| ascii_downcase; | ||
|
||
def epubchapname($cfi): | ||
$cfi | ||
| [match("(\\[[^\\]]+\\])+";"g")] | ||
| map( | ||
.string | ||
| gsub("[\\]\\[]+";"";"x") | ||
| gsub("(?<a>[a-zA-Z])[0]+(?<d>[0-9])";.a + " " + .d;"x") | ||
| gsub("[xX][0-9]{2,}[^a-zA-Z0-9]+";" ";"x") | ||
| gsub("([x\\.]+)?html";"";"x") | ||
| gsub("[_-]";" ";"x") | ||
| gsub("(?<a>[a-zA-Z])(?<n>[0-9])";.a + " " + .n;"x") | ||
| gsub("(?<a>[a-zA-Z])[0]{1,}(?<n>[1-9])";.a + " " +.n;"x") | ||
| gsub("^[pP][\\s]+";"Part ";"x") | ||
| gsub("^[Ccx]([hapter]+)? ";"Chapter";"xi") | ||
| gsub("^[Ss]([ection ]+)";"Section";"xi") | ||
| gsub("^[iI]([ntroduction]{1,}).*";"Introduction";"x") | ||
|
||
|select(length>0) | ||
) | unique[0] | ||
; | ||
|
||
def chaptername($location): | ||
$location | ||
| capture("\\[(?<chapter>[^\\]]+)\\]").chapter | ||
| gsub("[0-9]{6,}|margins|\\.?xhtml|epub|ebook|\\.html";"";"xi") | ||
| gsub("[_-]+";" ") | ||
| gsub("[\\s ]$";"";"x") | ||
| gsub("(?<w>[a-zA-Z])(?<d>[0-9])"; .w + " " + .d) | ||
| gsub("^[Ccx]([hapter ]+)([^0-9]+)?(?<c>[0-9])";"## Chapter "+ .c;"xi") | ||
| gsub("^[Ss]([ection ]+)? ";"### Section ";"xi") | ||
| gsub("^[iI][nt][cdinortu]+(?<s>[\\s])?";"## Introduction" + .s;"xi") | ||
| gsub(" [0]+(?<n>[1-9])";" " +.n) | ||
; | ||
|
||
|
||
def format_text: | ||
split("[\\n\\t]+";"x") | ||
| map(select(test("[a-zA-Z]")) | gsub("^[\\t\\s]+";"";"x")) | ||
| join("\n") | ||
| gsub("[\\s\\t]+$";"";"x") | ||
| gsub("\\s\\n(?<x>[a-xA-Z])"; " "+ .x) | ||
| gsub("[\\n]{2,}";"\n\n";"x") | ||
| gsub("(?<f>[a-z])\\n(?<s>[a-z])";.f + " " + .s;"x") | ||
; | ||
|
||
|
||
def format_paragraph($text): | ||
$text | ||
| unsmart | ||
| gsub("[\\s\\t]{2,}"; " ";"x") | ||
| gsub("[\\n]+"," \\n";"x") | ||
| gsub("(?<a>[^\\n]{60,72}) "; .a + "\n"; "m") | ||
; | ||
|
||
def wrap_text($text;$id): | ||
$text | ||
| gsub("[\\s\\t]{2,}"; " ";"x") | ||
| unsmart | ||
| split("[\\n]+";"x") | ||
| map("\(.) ") | ||
| join("\n") | ||
| gsub("(?<a>[^\\n]{60,72})[\\s](?<b>[a-zA-Z])"; "" + .a + "\n" + .b; "x") | ||
| split("[\\n]+";"x") | ||
| (.[0]|tostring) as $first | ||
| (.[1:]|map(select(test("[^\\s\\t\\n]"))|" \(.)")) as $last | ||
| [ "","* \($first)", $last, " [](#\($id))", "" ] | ||
| flatten(2) | ||
| join("\n"); | ||
|
||
|
||
def markdown_tmpl: | ||
[ | ||
"---", | ||
"title: \(if (.title|test(":")) then dquote(.title) else (.title) end)", | ||
"author: \(.author)", | ||
"asset_id: \(.assetid)", | ||
"date: \(.creationDate)", | ||
"modified: \(.modifiedDate)", | ||
"category: \(.tags)", | ||
"tags: [\(.tags)]", | ||
"count: \(.count)", | ||
"---", | ||
"", | ||
"# \(.title)", | ||
"", | ||
"by \(.author)", | ||
"", | ||
([.text]|flatten|join("\n")), | ||
"" | ||
] | ||
| join ("\n") | ||
; | ||
|
||
def get_chapter: | ||
. | ( | ||
if ((.ZFUTUREPROOFING5|length)>0) | ||
then .ZFUTUREPROOFING5 | ||
else chaptername(.ZANNOTATIONLOCATION) | ||
end); | ||
|
||
def get_chapter($o): $o|get_chapter; | ||
|
||
def rechapter: | ||
( if ((.ZFUTUREPROOFING5|length)>0) then "## \(.ZFUTUREPROOFING5)" | ||
elif (.ZANNOTATIONLOCATION|test("[Cc][ hapter]+";"x")) then | ||
"\(get_chapter)" | ||
else "" | ||
end | ||
); | ||
|
||
def rechapter($s): $s|rechapter; | ||
|
||
def group_by_chapter: | ||
sort_by(.booklocation) | ||
| group_by(.ZPLLOCATIONRANGESTART) | ||
| map([ | ||
(group_by(.chapter) | ||
| to_entries | ||
| map( | ||
.key as $k | | ||
.value | ( | ||
[.[0].chapter,"",(map(wrap_text(.ZANNOTATIONSELECTEDTEXT;.Z_PK))|join("\n\n")),""] | ||
| map(select(length>0)) | ||
| join("\n") | ||
) | ||
) | ||
) | ||
]) | ||
| flatten(2) | ||
| join("\n") | ||
; | ||
|
||
def bookcontent: | ||
map( select((.ZTITLE) and (.ZANNOTATIONSELECTEDTEXT|length) >10) | . + | ||
{ | ||
booklocation: epublocation(.ZANNOTATIONLOCATION), | ||
chapter: rechapter(.) | ||
} | ||
) | ||
| group_by(.ZASSETID) | ||
| map({ | ||
assetid: .[0].ZASSETID, | ||
title: (.[0].ZTITLE|gsub("\"";"") | gsub("\\([^0-9]+\\)"; "";"x")), | ||
author: .[0].ZAUTHOR, | ||
creationDate: min_by(.ZANNOTATIONCREATIONDATE).ZANNOTATIONCREATIONDATE, | ||
modifiedDate: max_by(.ZANNOTATIONCREATIONDATE).ZANNOTATIONCREATIONDATE, | ||
tags: get_tags(.[0].ZGENRE), | ||
slug: "\(get_author_slug(.[0].ZSORTAUTHOR))-\(slugify((.[0].ZTITLE|gsub("[^\\w\\s\\d]+";"";"x"))))", | ||
text: group_by_chapter|split("\n"), | ||
count: length | ||
}); | ||
|
||
def booksplit: bookcontent; | ||
|
||
def build: | ||
bookcontent | ||
| map( | ||
@sh "echo \( markdown_tmpl )" + " | cat -s > \(env.OUTDIR//"__test__")/\(.slug).md" | ||
) | ||
| join("\n\n"); | ||
|
||
def build_eval: | ||
bookcontent | ||
| map( | ||
@sh "echo \( markdown_tmpl )" + " | cat -s > \(env.OUTDIR//"__test__")/\(.slug).md" | ||
) | ||
| join("\n\n"); | ||
|
||
def create_tag_markdown: | ||
map({ | ||
title: ., | ||
content: ([ | ||
"---", | ||
"title: \"#\(.)\"", | ||
"tags: \(.)", | ||
"layout: tag", | ||
"---" | ||
] | join("\n")) | ||
}) | ||
| map(@sh "echo -e \(.content) >"+ "_tags/\(.title).md") | ||
| join("\n\n"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
#!/usr/bin/env bash | ||
set -e | ||
|
||
SCRIPT="$(realpath "$0")" | ||
DIR=${SCRIPT%/*} | ||
export OUTDIR=_data | ||
export ANNOTATIONS_FILE=annotations.json | ||
|
||
_log() { echo -e "\033[0;${2:-33}m$1\033[0m" 3>&2 2>&1 >&3 3>&-; } | ||
|
||
create_book_data() { | ||
_log "Creating books.json..." | ||
cat $ANNOTATIONS_FILE | jq -L $DIR 'include "books"; | ||
map( select((.ZTITLE) and (.ZANNOTATIONSELECTEDTEXT|length) >10) | | ||
. + { booklocation: epublocation(.ZANNOTATIONLOCATION), ZTITLE: (.ZTITLE|gsub("\"";"") | gsub("\\([^0-9]+\\)"; "";"x"))}) | ||
| group_by(.ZASSETID) | ||
| map({ | ||
assetid: .[0].ZASSETID, | ||
title: .[0].ZTITLE, | ||
author: .[0].ZAUTHOR, | ||
created: min_by(.ZANNOTATIONCREATIONDATE).ZANNOTATIONCREATIONDATE, | ||
modified: max_by(.ZANNOTATIONCREATIONDATE).ZANNOTATIONCREATIONDATE, | ||
tags: get_tags(.[0].ZGENRE), | ||
slug: "\(get_author_slug(.[0].ZAUTHOR))-\(slugify(.[0].ZTITLE))", | ||
count: length | ||
})| map(. + {permalink: "\(.tags)/\(.slug)"})' | ||
} | ||
|
||
create_genre_data() { | ||
_log "Creating genre.json..." | ||
cat $ANNOTATIONS_FILE | jq -L $DIR 'include "books"; map({tag: get_tags(.ZGENRE)})| unique' | ||
} | ||
|
||
create_activity_data() { | ||
_log "Creating activity.json..." | ||
cat $ANNOTATIONS_FILE | jq -L $DIR 'include "books"; | ||
map(select((.ZTITLE) and (.ZANNOTATIONSELECTEDTEXT|length) >10)) | ||
| sort_by(.ZANNOTATIONCREATIONDATE) | ||
| map({ | ||
id: .Z_PK, | ||
assetid: .ZASSETID, | ||
text: (.ZANNOTATIONSELECTEDTEXT|remove_citations|format_text), | ||
created: .ZANNOTATIONCREATIONDATE, | ||
location: .ZANNOTATIONLOCATION, | ||
cfi:(epublocation(.ZANNOTATIONLOCATION)| map(lpad(3))|join("-")), | ||
chapter: (if ((.ZFUTUREPROOFING5|length)>0) then .ZFUTUREPROOFING5 else chaptername(.ZANNOTATIONLOCATION) end), | ||
rangestart: .ZPLLOCATIONRANGESTART | ||
}) | ||
| sort_by(.id)' | ||
} | ||
|
||
create_word_data() { | ||
cat $ANNOTATIONS_FILE | jq 'map({ | ||
Z_PK, | ||
ZASSETID, | ||
words: (.ZANNOTATIONSELECTEDTEXT | ||
| gsub("[.?!] (?<a>[A-Z])"; (.a|ascii_downcase);"x") | ||
| gsub("\([39]|implode)"; "") | ||
| gsub("[^a-zA-Z]+";" ";"x")|split(" ") | ||
| map(select(length >4))|sort|group_by(.) | ||
| map([.[0],length]) | ||
| sort_by(.[1]) | ||
| map(join("-")) | ||
| reverse) | ||
})' | ||
} | ||
|
||
create_stats() { | ||
mkdir -p $OUTDIR/stats | ||
_log "Creating stats for monthly bookmarks" | ||
cat $OUTDIR/activity.json | | ||
jq 'sort_by(.created) | ||
| map(. + {groupby_label: (.created|fromdate|strftime("%b %Y"))}) | ||
| group_by(.groupby_label) | ||
| map({key: .[0].groupby_label, value: length}) | ||
| from_entries' >$OUTDIR/stats/bookmarks_per_month.json | ||
} | ||
|
||
while true; do | ||
case $1 in | ||
-o | --out) OUTDIR="$2" && shift ;; | ||
-r | --remote) FETCH_REMOTE=1 && shift ;; | ||
*.json) ANNOTATIONS_FILE="$1" && shift ;; | ||
esac | ||
shift || break | ||
done | ||
|
||
if [[ ! -f $ANNOTATIONS_FILE || $FETCH_REMOTE -eq 1 ]]; then | ||
_log "Fetching remote" | ||
ANNOTATIONS_FILE=/tmp/annotations.json | ||
curl --create-dirs -o $ANNOTATIONS_FILE https://raw.githubusercontent.com/nntrn/bookstand/assets/annotations.json | ||
fi | ||
|
||
if [[ -s $ANNOTATIONS_FILE ]]; then | ||
_log "===> Files will be saved to $OUTDIR <===" 36 | ||
mkdir -p $OUTDIR | ||
create_book_data >$OUTDIR/books.json | ||
create_genre_data >$OUTDIR/genre.json | ||
create_activity_data >$OUTDIR/activity.json | ||
create_stats | ||
else | ||
_log "annotations is empty" | ||
fi |