dsh-nerd-mode 0.4.6 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -6
- package/README.zh.md +11 -6
- package/assets/calibration.svg +69 -69
- package/assets/nerd.svg +22 -22
- package/assets/section.md +15 -15
- package/client.js +2170 -1806
- package/cordis.patch.yml +24 -24
- package/lib/index.js +838 -223
- package/lib/study-sessions.js +283 -0
- package/package.json +2 -2
- package/skills/convert-documents-to-markdown/SKILL.md +26 -26
- package/skills/diagram/SKILL.md +43 -19
- package/skills/diagram/scripts/check-svg.mjs +184 -0
- package/skills/humanizer/.claude-plugin/marketplace.json +18 -18
- package/skills/humanizer/.claude-plugin/plugin.json +15 -15
- package/skills/humanizer/.cursor-plugin/plugin.json +12 -12
- package/skills/humanizer/.github/ISSUE_TEMPLATE/config.yml +8 -8
- package/skills/humanizer/.github/ISSUE_TEMPLATE/new-pattern.yml +24 -24
- package/skills/humanizer/.github/ISSUE_TEMPLATE/rewrite-problem.yml +44 -44
- package/skills/humanizer/.github/workflows/validate.yml +29 -29
- package/skills/humanizer/AGENTS.md +54 -54
- package/skills/humanizer/CHANGELOG.md +116 -116
- package/skills/humanizer/LICENSE +21 -21
- package/skills/humanizer/README.md +206 -206
- package/skills/humanizer/SKILL.md +397 -397
- package/skills/humanizer/agents/openai.yaml +4 -4
- package/skills/humanizer/scripts/validate-package.py +146 -146
- package/skills/study/SKILL.md +81 -78
- package/skills/study-plus/SKILL.md +246 -246
- package/skills/study-plus/scripts/book-client.js +284 -284
- package/skills/study-plus/scripts/book-data.mjs +289 -289
- package/skills/study-plus/scripts/build-book.mjs +155 -155
- package/skills/writing-beats/SKILL.md +66 -66
- package/skills/writing-beats/agents/openai.yaml +5 -5
|
@@ -1,284 +1,284 @@
|
|
|
1
|
-
// Runs inside book.html. It turns am's flat document into a three-column book:
|
|
2
|
-
// chapter navigation, one section at a time, page contents, and search.
|
|
3
|
-
//
|
|
4
|
-
// This file is injected into <head>, not the end of <body>: am's own script
|
|
5
|
-
// leaves scripts placed after it inert. init() waits for the DOM.
|
|
6
|
-
(function () {
|
|
7
|
-
function init() {
|
|
8
|
-
var payload = document.getElementById('bk-book');
|
|
9
|
-
if (!payload) return;
|
|
10
|
-
|
|
11
|
-
var book = JSON.parse(payload.textContent);
|
|
12
|
-
var panels = [].slice.call(document.querySelectorAll('.am-doc-body > .am-panel'));
|
|
13
|
-
if (!panels.length) return;
|
|
14
|
-
|
|
15
|
-
var L = book.lang === 'en'
|
|
16
|
-
? { search: 'Search the book', toc: 'Contents', none: 'No match', hits: ' hits', chapter: 'Chapter', sections: 'sections', menu: 'Chapters', draft: 'Draft' }
|
|
17
|
-
: { search: '搜索全书', toc: '目录', none: '没有匹配', hits: ' 处', chapter: '第', sections: '节', menu: '章节', draft: '草稿' };
|
|
18
|
-
|
|
19
|
-
var layout = document.querySelector('.am-doc-layout');
|
|
20
|
-
var body = document.querySelector('.am-doc-body');
|
|
21
|
-
var current = 0;
|
|
22
|
-
var timer = 0;
|
|
23
|
-
|
|
24
|
-
function esc(s) {
|
|
25
|
-
return String(s).replace(/[&<>\"]/g, function (c) {
|
|
26
|
-
return { '&': '&', '<': '<', '>': '>', '\"': '"' }[c];
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function chapterTitle(chapter) {
|
|
31
|
-
return book.lang === 'en'
|
|
32
|
-
? L.chapter + ' ' + chapter.n + '. ' + chapter.name
|
|
33
|
-
: L.chapter + chapter.n + '章 ' + chapter.name;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function sectionNumber(unit) {
|
|
37
|
-
return unit.chapter + '.' + unit.section;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function chapterCount(chapter) {
|
|
41
|
-
return book.lang === 'en'
|
|
42
|
-
? chapter.count + (chapter.count === 1 ? ' section included' : ' sections included')
|
|
43
|
-
: '已收录 ' + chapter.count + ' ' + L.sections;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function sectionTitle(unit) {
|
|
47
|
-
return sectionNumber(unit) + ' ' + unit.title;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
var style = document.createElement('style');
|
|
51
|
-
style.textContent = [
|
|
52
|
-
':root { --bk-bar: 52px; }',
|
|
53
|
-
'body { padding-top: var(--bk-bar); }',
|
|
54
|
-
'.am-doc { max-width: 1440px; padding-top: 4px; }',
|
|
55
|
-
'.am-doc > header { display: none !important; }',
|
|
56
|
-
'.am-doc-layout, .am-doc-layout--notoc { grid-template-columns: 232px minmax(0, 1fr) 208px !important; max-width: none !important; gap: 28px !important; align-items: start; }',
|
|
57
|
-
'.am-toc { display: none !important; }',
|
|
58
|
-
'.am-toolbar { top: 10px !important; z-index: 30 !important; }',
|
|
59
|
-
'.bk-top { position: fixed; top: 0; left: 0; right: 0; height: var(--bk-bar); z-index: 25; display: flex; align-items: center; gap: 16px; padding: 0 24px; background: var(--paper); border-bottom: 1px solid var(--line-2); }',
|
|
60
|
-
'.am-toolbar .am-btn { display: none !important; }',
|
|
61
|
-
'.am-panel-id, .am-comment-btn { display: none !important; }',
|
|
62
|
-
'.am-doc-body .am-panel { border: 0 !important; background: transparent !important; border-radius: 0 !important; padding: 0 !important; }',
|
|
63
|
-
'.am-doc-body .am-panel + .am-panel { margin-top: 0; }',
|
|
64
|
-
'.am-doc-body .am-panel-head { padding-bottom: 12px; margin-bottom: 20px; }',
|
|
65
|
-
'.am-doc-body .am-panel-head h2 { font-size: 24px; font-weight: 650; line-height: 1.3; }',
|
|
66
|
-
'.am-doc-body .am-md h3 { font-size: 18px; font-weight: 650; margin-top: 28px; }',
|
|
67
|
-
'.am-doc-body .am-md h3:first-child { margin-top: 0; }',
|
|
68
|
-
'.am-doc-body .am-md h4 { font-size: 16px; font-weight: 600; margin-top: 20px; }',
|
|
69
|
-
// am's overflow-x:auto makes overflow-y auto too; a 1px overshoot draws scrollbar arrows on Windows.
|
|
70
|
-
'.am-math-block { overflow-y: hidden; }',
|
|
71
|
-
'.bk-context { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin: 0 0 8px; font-size: 13px; }',
|
|
72
|
-
'.bk-context-chapter { color: var(--ink-2); font-weight: 600; }',
|
|
73
|
-
'.bk-context-section { color: var(--ink-3); white-space: nowrap; }',
|
|
74
|
-
'.bk-title { flex: 0 1 auto; min-width: 0; font-weight: 650; font-size: 15px; color: var(--ink); text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }',
|
|
75
|
-
'.bk-search { position: relative; margin-left: 18px; }',
|
|
76
|
-
'.bk-search input { width: 210px; height: 30px; padding: 0 10px; border: 1px solid var(--line-2); border-radius: 6px; background: var(--bg); color: var(--ink); font: inherit; font-size: 13px; }',
|
|
77
|
-
'.bk-results { position: absolute; top: 36px; right: 0; width: min(300px, calc(100vw - 24px)); margin: 0; padding: 4px; list-style: none; background: var(--paper); border: 1px solid var(--line-2); border-radius: 8px; box-shadow: 0 10px 28px rgba(0,0,0,.14); max-height: 60vh; overflow: auto; z-index: 40; }',
|
|
78
|
-
'.bk-results li { padding: 6px 8px; border-radius: 6px; cursor: pointer; font-size: 13px; color: var(--ink); }',
|
|
79
|
-
'.bk-results li:hover { background: var(--fill); }',
|
|
80
|
-
'.bk-results .bk-n { color: var(--ink-3); font-size: 12px; margin-left: 6px; }',
|
|
81
|
-
'.bk-nav { position: sticky; top: calc(var(--bk-bar) + 16px); max-height: calc(100vh - var(--bk-bar) - 40px); overflow: auto; font-size: 13px; padding-right: 6px; }',
|
|
82
|
-
'.bk-ch { margin: 0 0 12px; }',
|
|
83
|
-
'.bk-ch > summary { cursor: pointer; font-weight: 600; color: var(--ink); padding: 3px 0; }',
|
|
84
|
-
'.bk-ch > summary::marker { color: var(--ink-3); }',
|
|
85
|
-
'.bk-ch-count { color: var(--ink-3); font-size: 11px; font-weight: 400; margin-left: 6px; white-space: nowrap; }',
|
|
86
|
-
'.bk-draft { color: var(--ink-3); border: 1px solid var(--line-2); border-radius: 4px; padding: 0 4px; margin-left: 6px; font-size: 11px; letter-spacing: .02em; vertical-align: middle; text-transform: uppercase; }',
|
|
87
|
-
'.bk-u { display: block; padding: 4px 0 4px 12px; margin-left: 2px; color: var(--ink-2); text-decoration: none; border-left: 2px solid var(--line-2); }',
|
|
88
|
-
'.bk-u:hover { color: var(--ink); }',
|
|
89
|
-
'.bk-u.on { color: var(--accent); border-left-color: var(--accent); font-weight: 600; }',
|
|
90
|
-
'.bk-toc { position: sticky; top: calc(var(--bk-bar) + 16px); max-height: calc(100vh - var(--bk-bar) - 40px); overflow: auto; font-size: 12.5px; }',
|
|
91
|
-
'.bk-toc-t { color: var(--ink-3); margin-bottom: 6px; }',
|
|
92
|
-
'.bk-h { display: block; padding: 3px 0; color: var(--ink-2); text-decoration: none; }',
|
|
93
|
-
'.bk-h.lv2 { padding-left: 12px; font-size: 12px; }',
|
|
94
|
-
'.bk-h:hover, .bk-h.on { color: var(--accent); }',
|
|
95
|
-
'.bk-mobile { display: none; position: relative; }',
|
|
96
|
-
'.bk-mobile > summary { list-style: none; cursor: pointer; color: var(--ink); font-size: 12px; padding: 6px 8px; border: 1px solid var(--line-2); border-radius: 6px; white-space: nowrap; }',
|
|
97
|
-
'.bk-mobile > summary::-webkit-details-marker { display: none; }',
|
|
98
|
-
'.bk-mobile-list { position: absolute; top: calc(100% + 8px); right: 0; width: min(300px, calc(100vw - 24px)); max-height: calc(100vh - var(--bk-bar) - 24px); overflow: auto; padding: 12px; background: var(--paper); border: 1px solid var(--line-2); border-radius: 8px; box-shadow: 0 10px 28px rgba(0,0,0,.14); z-index: 40; }',
|
|
99
|
-
'.bk-nav-mobile { position: static; max-height: none; overflow: visible; padding-right: 0; }',
|
|
100
|
-
'.am-panel[hidden] { display: none !important; }',
|
|
101
|
-
'@media print { .bk-nav, .bk-toc, .bk-top, .am-toolbar { display: none !important; } body { padding-top: 0; } .am-panel[hidden] { display: block !important; } }',
|
|
102
|
-
'@media (max-width: 1100px) { .bk-toc { display: none; } .am-doc-layout, .am-doc-layout--notoc { grid-template-columns: 200px minmax(0, 1fr) !important; } }',
|
|
103
|
-
'@media (max-width: 800px) { .bk-top { gap: 8px; padding: 0 12px; } .bk-title { flex: 1 1 0; } .bk-search { margin-left: auto; } .bk-search input { width: clamp(88px, 34vw, 150px); } .bk-mobile { display: block; } .bk-nav { display: none; } .bk-nav-mobile { display: block; } .am-doc-layout, .am-doc-layout--notoc { grid-template-columns: minmax(0, 1fr) !important; } .bk-context { flex-wrap: wrap; } .bk-context-section { white-space: normal; } }'
|
|
104
|
-
].join('\n');
|
|
105
|
-
document.head.appendChild(style);
|
|
106
|
-
|
|
107
|
-
var top = document.createElement('header');
|
|
108
|
-
top.className = 'bk-top';
|
|
109
|
-
top.innerHTML =
|
|
110
|
-
'<a class="bk-title" href="#' + esc(panels[0].id) + '">' + esc(book.title) + '</a>' +
|
|
111
|
-
'<div class="bk-search"><input id="bk-q" type="search" placeholder="' + L.search + '" aria-label="' + L.search + '"><ul id="bk-results" class="bk-results" hidden></ul></div>' +
|
|
112
|
-
'<details class="bk-mobile"><summary>' + L.menu + '</summary><div class="bk-mobile-list"><nav class="bk-nav bk-nav-mobile"></nav></div></details>';
|
|
113
|
-
document.body.appendChild(top);
|
|
114
|
-
|
|
115
|
-
var nav = document.createElement('nav');
|
|
116
|
-
nav.className = 'bk-nav';
|
|
117
|
-
var groups = (book.chapters || []).map(function (chapter) { return { chapter: chapter, units: [] }; });
|
|
118
|
-
book.units.forEach(function (u) {
|
|
119
|
-
for (var i = 0; i < groups.length; i++) {
|
|
120
|
-
if (groups[i].chapter.n === u.chapter) {
|
|
121
|
-
groups[i].units.push(u);
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
function draftTag(u) {
|
|
128
|
-
return u.status === 'draft' ? '<span class="bk-draft">' + esc(L.draft) + '</span>' : '';
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function link(u) {
|
|
132
|
-
var index = Number(u.index);
|
|
133
|
-
return '<a class="bk-u" href="#' + esc(panels[index].id) + '" data-i="' + esc(index) + '">' +
|
|
134
|
-
esc(sectionTitle(u)) + draftTag(u) + '</a>';
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
var navHtml = '';
|
|
138
|
-
groups.forEach(function (g) {
|
|
139
|
-
if (!g.units.length) return;
|
|
140
|
-
navHtml += '<details class="bk-ch" open><summary>' + esc(chapterTitle(g.chapter)) +
|
|
141
|
-
'<span class="bk-ch-count">' + esc(chapterCount(g.chapter)) + '</span></summary>' +
|
|
142
|
-
g.units.map(link).join('') + '</details>';
|
|
143
|
-
g.units.forEach(function (u) {
|
|
144
|
-
var panel = panels[Number(u.index)];
|
|
145
|
-
var context = document.createElement('div');
|
|
146
|
-
context.className = 'bk-context';
|
|
147
|
-
var chapter = document.createElement('span');
|
|
148
|
-
chapter.className = 'bk-context-chapter';
|
|
149
|
-
chapter.textContent = chapterTitle(g.chapter);
|
|
150
|
-
var section = document.createElement('span');
|
|
151
|
-
section.className = 'bk-context-section';
|
|
152
|
-
section.innerHTML = esc(sectionNumber(u)) + draftTag(u);
|
|
153
|
-
context.appendChild(chapter);
|
|
154
|
-
context.appendChild(section);
|
|
155
|
-
var heading = panel.querySelector('.am-panel-head');
|
|
156
|
-
panel.insertBefore(context, heading || panel.firstChild);
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
nav.innerHTML = navHtml;
|
|
160
|
-
layout.insertBefore(nav, body);
|
|
161
|
-
var mobileNav = top.querySelector('.bk-nav-mobile');
|
|
162
|
-
mobileNav.innerHTML = navHtml;
|
|
163
|
-
var mobileMenu = top.querySelector('.bk-mobile');
|
|
164
|
-
|
|
165
|
-
var toc = document.createElement('aside');
|
|
166
|
-
toc.className = 'bk-toc';
|
|
167
|
-
layout.appendChild(toc);
|
|
168
|
-
|
|
169
|
-
function buildToc(i) {
|
|
170
|
-
var heads = [].slice.call(panels[i].querySelectorAll('h3, h4'));
|
|
171
|
-
if (!heads.length) { toc.innerHTML = ''; toc.hidden = true; return; }
|
|
172
|
-
toc.hidden = false;
|
|
173
|
-
toc.innerHTML = '<div class="bk-toc-t">' + L.toc + '</div>' + heads.map(function (h, k) {
|
|
174
|
-
if (!h.id) h.id = panels[i].id + '-h' + k;
|
|
175
|
-
return '<a class="bk-h' + (h.tagName === 'H4' ? ' lv2' : '') + '" href="#' + esc(h.id) + '" data-t="' + esc(h.id) + '">' + esc(h.textContent) + '</a>';
|
|
176
|
-
}).join('');
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function show(i, silent) {
|
|
180
|
-
current = i;
|
|
181
|
-
panels.forEach(function (p, j) { p.hidden = j !== i; });
|
|
182
|
-
[nav, mobileNav].forEach(function (menu) {
|
|
183
|
-
[].forEach.call(menu.querySelectorAll('.bk-u'), function (a) {
|
|
184
|
-
a.classList.toggle('on', Number(a.dataset.i) === i);
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
buildToc(i);
|
|
188
|
-
if (!silent) history.replaceState(null, '', '#' + panels[i].id);
|
|
189
|
-
window.scrollTo(0, 0);
|
|
190
|
-
spy();
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function bindNavigation(menu, isMobile) {
|
|
194
|
-
menu.addEventListener('click', function (e) {
|
|
195
|
-
var a = e.target.closest('.bk-u');
|
|
196
|
-
if (!a) return;
|
|
197
|
-
e.preventDefault();
|
|
198
|
-
show(Number(a.dataset.i));
|
|
199
|
-
if (isMobile) mobileMenu.open = false;
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
bindNavigation(nav, false);
|
|
204
|
-
bindNavigation(mobileNav, true);
|
|
205
|
-
|
|
206
|
-
toc.addEventListener('click', function (e) {
|
|
207
|
-
var a = e.target.closest('.bk-h');
|
|
208
|
-
if (!a) return;
|
|
209
|
-
e.preventDefault();
|
|
210
|
-
var h = document.getElementById(a.dataset.t);
|
|
211
|
-
if (h) h.scrollIntoView({ block: 'start', behavior: 'smooth' });
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
function spy() {
|
|
215
|
-
var heads = [].slice.call(panels[current].querySelectorAll('h3, h4'));
|
|
216
|
-
if (!heads.length) return;
|
|
217
|
-
var line = window.scrollY + 120;
|
|
218
|
-
var active = heads[0];
|
|
219
|
-
heads.forEach(function (h) { if (h.getBoundingClientRect().top + window.scrollY <= line) active = h; });
|
|
220
|
-
[].forEach.call(toc.querySelectorAll('.bk-h'), function (a) {
|
|
221
|
-
a.classList.toggle('on', a.dataset.t === active.id);
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
window.addEventListener('scroll', function () {
|
|
226
|
-
clearTimeout(timer);
|
|
227
|
-
timer = setTimeout(spy, 90);
|
|
228
|
-
}, { passive: true });
|
|
229
|
-
|
|
230
|
-
var q = document.getElementById('bk-q');
|
|
231
|
-
var results = document.getElementById('bk-results');
|
|
232
|
-
|
|
233
|
-
q.addEventListener('input', function () {
|
|
234
|
-
var term = q.value.trim();
|
|
235
|
-
if (term.length < 2) { results.hidden = true; results.innerHTML = ''; return; }
|
|
236
|
-
var lower = term.toLowerCase();
|
|
237
|
-
var hits = [];
|
|
238
|
-
book.units.forEach(function (u) {
|
|
239
|
-
var text = panels[u.index].textContent.toLowerCase();
|
|
240
|
-
var n = text.split(lower).length - 1;
|
|
241
|
-
if (n) hits.push({ u: u, n: n });
|
|
242
|
-
});
|
|
243
|
-
if (!hits.length) {
|
|
244
|
-
results.innerHTML = '<li>' + L.none + '</li>';
|
|
245
|
-
} else {
|
|
246
|
-
results.innerHTML = hits.slice(0, 8).map(function (h) {
|
|
247
|
-
return '<li data-i="' + esc(h.u.index) + '">' + esc(sectionTitle(h.u)) +
|
|
248
|
-
'<span class="bk-n">' + h.n + L.hits + '</span></li>';
|
|
249
|
-
}).join('');
|
|
250
|
-
}
|
|
251
|
-
results.hidden = false;
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
results.addEventListener('click', function (e) {
|
|
255
|
-
var li = e.target.closest('li[data-i]');
|
|
256
|
-
if (!li) return;
|
|
257
|
-
var i = Number(li.dataset.i);
|
|
258
|
-
var term = q.value.trim();
|
|
259
|
-
show(i);
|
|
260
|
-
results.hidden = true;
|
|
261
|
-
// shortcut: window.find is Chromium-only and jumps to the first match;
|
|
262
|
-
// the unit still opens when the host lacks it.
|
|
263
|
-
setTimeout(function () {
|
|
264
|
-
try { window.find(term, false, false, true); } catch (err) { /* no jump */ }
|
|
265
|
-
}, 60);
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
document.addEventListener('click', function (e) {
|
|
269
|
-
if (!e.target.closest('.bk-search')) results.hidden = true;
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
var start = 0;
|
|
273
|
-
var hash = decodeURIComponent(location.hash.slice(1));
|
|
274
|
-
for (var i = 0; i < panels.length; i++) if (panels[i].id === hash) start = i;
|
|
275
|
-
show(start, !hash);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot);
|
|
279
|
-
else boot();
|
|
280
|
-
|
|
281
|
-
function boot() {
|
|
282
|
-
try { init(); } catch (e) { console.error('[book]', e); }
|
|
283
|
-
}
|
|
284
|
-
})();
|
|
1
|
+
// Runs inside book.html. It turns am's flat document into a three-column book:
|
|
2
|
+
// chapter navigation, one section at a time, page contents, and search.
|
|
3
|
+
//
|
|
4
|
+
// This file is injected into <head>, not the end of <body>: am's own script
|
|
5
|
+
// leaves scripts placed after it inert. init() waits for the DOM.
|
|
6
|
+
(function () {
|
|
7
|
+
function init() {
|
|
8
|
+
var payload = document.getElementById('bk-book');
|
|
9
|
+
if (!payload) return;
|
|
10
|
+
|
|
11
|
+
var book = JSON.parse(payload.textContent);
|
|
12
|
+
var panels = [].slice.call(document.querySelectorAll('.am-doc-body > .am-panel'));
|
|
13
|
+
if (!panels.length) return;
|
|
14
|
+
|
|
15
|
+
var L = book.lang === 'en'
|
|
16
|
+
? { search: 'Search the book', toc: 'Contents', none: 'No match', hits: ' hits', chapter: 'Chapter', sections: 'sections', menu: 'Chapters', draft: 'Draft' }
|
|
17
|
+
: { search: '搜索全书', toc: '目录', none: '没有匹配', hits: ' 处', chapter: '第', sections: '节', menu: '章节', draft: '草稿' };
|
|
18
|
+
|
|
19
|
+
var layout = document.querySelector('.am-doc-layout');
|
|
20
|
+
var body = document.querySelector('.am-doc-body');
|
|
21
|
+
var current = 0;
|
|
22
|
+
var timer = 0;
|
|
23
|
+
|
|
24
|
+
function esc(s) {
|
|
25
|
+
return String(s).replace(/[&<>\"]/g, function (c) {
|
|
26
|
+
return { '&': '&', '<': '<', '>': '>', '\"': '"' }[c];
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function chapterTitle(chapter) {
|
|
31
|
+
return book.lang === 'en'
|
|
32
|
+
? L.chapter + ' ' + chapter.n + '. ' + chapter.name
|
|
33
|
+
: L.chapter + chapter.n + '章 ' + chapter.name;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function sectionNumber(unit) {
|
|
37
|
+
return unit.chapter + '.' + unit.section;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function chapterCount(chapter) {
|
|
41
|
+
return book.lang === 'en'
|
|
42
|
+
? chapter.count + (chapter.count === 1 ? ' section included' : ' sections included')
|
|
43
|
+
: '已收录 ' + chapter.count + ' ' + L.sections;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function sectionTitle(unit) {
|
|
47
|
+
return sectionNumber(unit) + ' ' + unit.title;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
var style = document.createElement('style');
|
|
51
|
+
style.textContent = [
|
|
52
|
+
':root { --bk-bar: 52px; }',
|
|
53
|
+
'body { padding-top: var(--bk-bar); }',
|
|
54
|
+
'.am-doc { max-width: 1440px; padding-top: 4px; }',
|
|
55
|
+
'.am-doc > header { display: none !important; }',
|
|
56
|
+
'.am-doc-layout, .am-doc-layout--notoc { grid-template-columns: 232px minmax(0, 1fr) 208px !important; max-width: none !important; gap: 28px !important; align-items: start; }',
|
|
57
|
+
'.am-toc { display: none !important; }',
|
|
58
|
+
'.am-toolbar { top: 10px !important; z-index: 30 !important; }',
|
|
59
|
+
'.bk-top { position: fixed; top: 0; left: 0; right: 0; height: var(--bk-bar); z-index: 25; display: flex; align-items: center; gap: 16px; padding: 0 24px; background: var(--paper); border-bottom: 1px solid var(--line-2); }',
|
|
60
|
+
'.am-toolbar .am-btn { display: none !important; }',
|
|
61
|
+
'.am-panel-id, .am-comment-btn { display: none !important; }',
|
|
62
|
+
'.am-doc-body .am-panel { border: 0 !important; background: transparent !important; border-radius: 0 !important; padding: 0 !important; }',
|
|
63
|
+
'.am-doc-body .am-panel + .am-panel { margin-top: 0; }',
|
|
64
|
+
'.am-doc-body .am-panel-head { padding-bottom: 12px; margin-bottom: 20px; }',
|
|
65
|
+
'.am-doc-body .am-panel-head h2 { font-size: 24px; font-weight: 650; line-height: 1.3; }',
|
|
66
|
+
'.am-doc-body .am-md h3 { font-size: 18px; font-weight: 650; margin-top: 28px; }',
|
|
67
|
+
'.am-doc-body .am-md h3:first-child { margin-top: 0; }',
|
|
68
|
+
'.am-doc-body .am-md h4 { font-size: 16px; font-weight: 600; margin-top: 20px; }',
|
|
69
|
+
// am's overflow-x:auto makes overflow-y auto too; a 1px overshoot draws scrollbar arrows on Windows.
|
|
70
|
+
'.am-math-block { overflow-y: hidden; }',
|
|
71
|
+
'.bk-context { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin: 0 0 8px; font-size: 13px; }',
|
|
72
|
+
'.bk-context-chapter { color: var(--ink-2); font-weight: 600; }',
|
|
73
|
+
'.bk-context-section { color: var(--ink-3); white-space: nowrap; }',
|
|
74
|
+
'.bk-title { flex: 0 1 auto; min-width: 0; font-weight: 650; font-size: 15px; color: var(--ink); text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }',
|
|
75
|
+
'.bk-search { position: relative; margin-left: 18px; }',
|
|
76
|
+
'.bk-search input { width: 210px; height: 30px; padding: 0 10px; border: 1px solid var(--line-2); border-radius: 6px; background: var(--bg); color: var(--ink); font: inherit; font-size: 13px; }',
|
|
77
|
+
'.bk-results { position: absolute; top: 36px; right: 0; width: min(300px, calc(100vw - 24px)); margin: 0; padding: 4px; list-style: none; background: var(--paper); border: 1px solid var(--line-2); border-radius: 8px; box-shadow: 0 10px 28px rgba(0,0,0,.14); max-height: 60vh; overflow: auto; z-index: 40; }',
|
|
78
|
+
'.bk-results li { padding: 6px 8px; border-radius: 6px; cursor: pointer; font-size: 13px; color: var(--ink); }',
|
|
79
|
+
'.bk-results li:hover { background: var(--fill); }',
|
|
80
|
+
'.bk-results .bk-n { color: var(--ink-3); font-size: 12px; margin-left: 6px; }',
|
|
81
|
+
'.bk-nav { position: sticky; top: calc(var(--bk-bar) + 16px); max-height: calc(100vh - var(--bk-bar) - 40px); overflow: auto; font-size: 13px; padding-right: 6px; }',
|
|
82
|
+
'.bk-ch { margin: 0 0 12px; }',
|
|
83
|
+
'.bk-ch > summary { cursor: pointer; font-weight: 600; color: var(--ink); padding: 3px 0; }',
|
|
84
|
+
'.bk-ch > summary::marker { color: var(--ink-3); }',
|
|
85
|
+
'.bk-ch-count { color: var(--ink-3); font-size: 11px; font-weight: 400; margin-left: 6px; white-space: nowrap; }',
|
|
86
|
+
'.bk-draft { color: var(--ink-3); border: 1px solid var(--line-2); border-radius: 4px; padding: 0 4px; margin-left: 6px; font-size: 11px; letter-spacing: .02em; vertical-align: middle; text-transform: uppercase; }',
|
|
87
|
+
'.bk-u { display: block; padding: 4px 0 4px 12px; margin-left: 2px; color: var(--ink-2); text-decoration: none; border-left: 2px solid var(--line-2); }',
|
|
88
|
+
'.bk-u:hover { color: var(--ink); }',
|
|
89
|
+
'.bk-u.on { color: var(--accent); border-left-color: var(--accent); font-weight: 600; }',
|
|
90
|
+
'.bk-toc { position: sticky; top: calc(var(--bk-bar) + 16px); max-height: calc(100vh - var(--bk-bar) - 40px); overflow: auto; font-size: 12.5px; }',
|
|
91
|
+
'.bk-toc-t { color: var(--ink-3); margin-bottom: 6px; }',
|
|
92
|
+
'.bk-h { display: block; padding: 3px 0; color: var(--ink-2); text-decoration: none; }',
|
|
93
|
+
'.bk-h.lv2 { padding-left: 12px; font-size: 12px; }',
|
|
94
|
+
'.bk-h:hover, .bk-h.on { color: var(--accent); }',
|
|
95
|
+
'.bk-mobile { display: none; position: relative; }',
|
|
96
|
+
'.bk-mobile > summary { list-style: none; cursor: pointer; color: var(--ink); font-size: 12px; padding: 6px 8px; border: 1px solid var(--line-2); border-radius: 6px; white-space: nowrap; }',
|
|
97
|
+
'.bk-mobile > summary::-webkit-details-marker { display: none; }',
|
|
98
|
+
'.bk-mobile-list { position: absolute; top: calc(100% + 8px); right: 0; width: min(300px, calc(100vw - 24px)); max-height: calc(100vh - var(--bk-bar) - 24px); overflow: auto; padding: 12px; background: var(--paper); border: 1px solid var(--line-2); border-radius: 8px; box-shadow: 0 10px 28px rgba(0,0,0,.14); z-index: 40; }',
|
|
99
|
+
'.bk-nav-mobile { position: static; max-height: none; overflow: visible; padding-right: 0; }',
|
|
100
|
+
'.am-panel[hidden] { display: none !important; }',
|
|
101
|
+
'@media print { .bk-nav, .bk-toc, .bk-top, .am-toolbar { display: none !important; } body { padding-top: 0; } .am-panel[hidden] { display: block !important; } }',
|
|
102
|
+
'@media (max-width: 1100px) { .bk-toc { display: none; } .am-doc-layout, .am-doc-layout--notoc { grid-template-columns: 200px minmax(0, 1fr) !important; } }',
|
|
103
|
+
'@media (max-width: 800px) { .bk-top { gap: 8px; padding: 0 12px; } .bk-title { flex: 1 1 0; } .bk-search { margin-left: auto; } .bk-search input { width: clamp(88px, 34vw, 150px); } .bk-mobile { display: block; } .bk-nav { display: none; } .bk-nav-mobile { display: block; } .am-doc-layout, .am-doc-layout--notoc { grid-template-columns: minmax(0, 1fr) !important; } .bk-context { flex-wrap: wrap; } .bk-context-section { white-space: normal; } }'
|
|
104
|
+
].join('\n');
|
|
105
|
+
document.head.appendChild(style);
|
|
106
|
+
|
|
107
|
+
var top = document.createElement('header');
|
|
108
|
+
top.className = 'bk-top';
|
|
109
|
+
top.innerHTML =
|
|
110
|
+
'<a class="bk-title" href="#' + esc(panels[0].id) + '">' + esc(book.title) + '</a>' +
|
|
111
|
+
'<div class="bk-search"><input id="bk-q" type="search" placeholder="' + L.search + '" aria-label="' + L.search + '"><ul id="bk-results" class="bk-results" hidden></ul></div>' +
|
|
112
|
+
'<details class="bk-mobile"><summary>' + L.menu + '</summary><div class="bk-mobile-list"><nav class="bk-nav bk-nav-mobile"></nav></div></details>';
|
|
113
|
+
document.body.appendChild(top);
|
|
114
|
+
|
|
115
|
+
var nav = document.createElement('nav');
|
|
116
|
+
nav.className = 'bk-nav';
|
|
117
|
+
var groups = (book.chapters || []).map(function (chapter) { return { chapter: chapter, units: [] }; });
|
|
118
|
+
book.units.forEach(function (u) {
|
|
119
|
+
for (var i = 0; i < groups.length; i++) {
|
|
120
|
+
if (groups[i].chapter.n === u.chapter) {
|
|
121
|
+
groups[i].units.push(u);
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
function draftTag(u) {
|
|
128
|
+
return u.status === 'draft' ? '<span class="bk-draft">' + esc(L.draft) + '</span>' : '';
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function link(u) {
|
|
132
|
+
var index = Number(u.index);
|
|
133
|
+
return '<a class="bk-u" href="#' + esc(panels[index].id) + '" data-i="' + esc(index) + '">' +
|
|
134
|
+
esc(sectionTitle(u)) + draftTag(u) + '</a>';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
var navHtml = '';
|
|
138
|
+
groups.forEach(function (g) {
|
|
139
|
+
if (!g.units.length) return;
|
|
140
|
+
navHtml += '<details class="bk-ch" open><summary>' + esc(chapterTitle(g.chapter)) +
|
|
141
|
+
'<span class="bk-ch-count">' + esc(chapterCount(g.chapter)) + '</span></summary>' +
|
|
142
|
+
g.units.map(link).join('') + '</details>';
|
|
143
|
+
g.units.forEach(function (u) {
|
|
144
|
+
var panel = panels[Number(u.index)];
|
|
145
|
+
var context = document.createElement('div');
|
|
146
|
+
context.className = 'bk-context';
|
|
147
|
+
var chapter = document.createElement('span');
|
|
148
|
+
chapter.className = 'bk-context-chapter';
|
|
149
|
+
chapter.textContent = chapterTitle(g.chapter);
|
|
150
|
+
var section = document.createElement('span');
|
|
151
|
+
section.className = 'bk-context-section';
|
|
152
|
+
section.innerHTML = esc(sectionNumber(u)) + draftTag(u);
|
|
153
|
+
context.appendChild(chapter);
|
|
154
|
+
context.appendChild(section);
|
|
155
|
+
var heading = panel.querySelector('.am-panel-head');
|
|
156
|
+
panel.insertBefore(context, heading || panel.firstChild);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
nav.innerHTML = navHtml;
|
|
160
|
+
layout.insertBefore(nav, body);
|
|
161
|
+
var mobileNav = top.querySelector('.bk-nav-mobile');
|
|
162
|
+
mobileNav.innerHTML = navHtml;
|
|
163
|
+
var mobileMenu = top.querySelector('.bk-mobile');
|
|
164
|
+
|
|
165
|
+
var toc = document.createElement('aside');
|
|
166
|
+
toc.className = 'bk-toc';
|
|
167
|
+
layout.appendChild(toc);
|
|
168
|
+
|
|
169
|
+
function buildToc(i) {
|
|
170
|
+
var heads = [].slice.call(panels[i].querySelectorAll('h3, h4'));
|
|
171
|
+
if (!heads.length) { toc.innerHTML = ''; toc.hidden = true; return; }
|
|
172
|
+
toc.hidden = false;
|
|
173
|
+
toc.innerHTML = '<div class="bk-toc-t">' + L.toc + '</div>' + heads.map(function (h, k) {
|
|
174
|
+
if (!h.id) h.id = panels[i].id + '-h' + k;
|
|
175
|
+
return '<a class="bk-h' + (h.tagName === 'H4' ? ' lv2' : '') + '" href="#' + esc(h.id) + '" data-t="' + esc(h.id) + '">' + esc(h.textContent) + '</a>';
|
|
176
|
+
}).join('');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function show(i, silent) {
|
|
180
|
+
current = i;
|
|
181
|
+
panels.forEach(function (p, j) { p.hidden = j !== i; });
|
|
182
|
+
[nav, mobileNav].forEach(function (menu) {
|
|
183
|
+
[].forEach.call(menu.querySelectorAll('.bk-u'), function (a) {
|
|
184
|
+
a.classList.toggle('on', Number(a.dataset.i) === i);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
buildToc(i);
|
|
188
|
+
if (!silent) history.replaceState(null, '', '#' + panels[i].id);
|
|
189
|
+
window.scrollTo(0, 0);
|
|
190
|
+
spy();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function bindNavigation(menu, isMobile) {
|
|
194
|
+
menu.addEventListener('click', function (e) {
|
|
195
|
+
var a = e.target.closest('.bk-u');
|
|
196
|
+
if (!a) return;
|
|
197
|
+
e.preventDefault();
|
|
198
|
+
show(Number(a.dataset.i));
|
|
199
|
+
if (isMobile) mobileMenu.open = false;
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
bindNavigation(nav, false);
|
|
204
|
+
bindNavigation(mobileNav, true);
|
|
205
|
+
|
|
206
|
+
toc.addEventListener('click', function (e) {
|
|
207
|
+
var a = e.target.closest('.bk-h');
|
|
208
|
+
if (!a) return;
|
|
209
|
+
e.preventDefault();
|
|
210
|
+
var h = document.getElementById(a.dataset.t);
|
|
211
|
+
if (h) h.scrollIntoView({ block: 'start', behavior: 'smooth' });
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
function spy() {
|
|
215
|
+
var heads = [].slice.call(panels[current].querySelectorAll('h3, h4'));
|
|
216
|
+
if (!heads.length) return;
|
|
217
|
+
var line = window.scrollY + 120;
|
|
218
|
+
var active = heads[0];
|
|
219
|
+
heads.forEach(function (h) { if (h.getBoundingClientRect().top + window.scrollY <= line) active = h; });
|
|
220
|
+
[].forEach.call(toc.querySelectorAll('.bk-h'), function (a) {
|
|
221
|
+
a.classList.toggle('on', a.dataset.t === active.id);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
window.addEventListener('scroll', function () {
|
|
226
|
+
clearTimeout(timer);
|
|
227
|
+
timer = setTimeout(spy, 90);
|
|
228
|
+
}, { passive: true });
|
|
229
|
+
|
|
230
|
+
var q = document.getElementById('bk-q');
|
|
231
|
+
var results = document.getElementById('bk-results');
|
|
232
|
+
|
|
233
|
+
q.addEventListener('input', function () {
|
|
234
|
+
var term = q.value.trim();
|
|
235
|
+
if (term.length < 2) { results.hidden = true; results.innerHTML = ''; return; }
|
|
236
|
+
var lower = term.toLowerCase();
|
|
237
|
+
var hits = [];
|
|
238
|
+
book.units.forEach(function (u) {
|
|
239
|
+
var text = panels[u.index].textContent.toLowerCase();
|
|
240
|
+
var n = text.split(lower).length - 1;
|
|
241
|
+
if (n) hits.push({ u: u, n: n });
|
|
242
|
+
});
|
|
243
|
+
if (!hits.length) {
|
|
244
|
+
results.innerHTML = '<li>' + L.none + '</li>';
|
|
245
|
+
} else {
|
|
246
|
+
results.innerHTML = hits.slice(0, 8).map(function (h) {
|
|
247
|
+
return '<li data-i="' + esc(h.u.index) + '">' + esc(sectionTitle(h.u)) +
|
|
248
|
+
'<span class="bk-n">' + h.n + L.hits + '</span></li>';
|
|
249
|
+
}).join('');
|
|
250
|
+
}
|
|
251
|
+
results.hidden = false;
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
results.addEventListener('click', function (e) {
|
|
255
|
+
var li = e.target.closest('li[data-i]');
|
|
256
|
+
if (!li) return;
|
|
257
|
+
var i = Number(li.dataset.i);
|
|
258
|
+
var term = q.value.trim();
|
|
259
|
+
show(i);
|
|
260
|
+
results.hidden = true;
|
|
261
|
+
// shortcut: window.find is Chromium-only and jumps to the first match;
|
|
262
|
+
// the unit still opens when the host lacks it.
|
|
263
|
+
setTimeout(function () {
|
|
264
|
+
try { window.find(term, false, false, true); } catch (err) { /* no jump */ }
|
|
265
|
+
}, 60);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
document.addEventListener('click', function (e) {
|
|
269
|
+
if (!e.target.closest('.bk-search')) results.hidden = true;
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
var start = 0;
|
|
273
|
+
var hash = decodeURIComponent(location.hash.slice(1));
|
|
274
|
+
for (var i = 0; i < panels.length; i++) if (panels[i].id === hash) start = i;
|
|
275
|
+
show(start, !hash);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot);
|
|
279
|
+
else boot();
|
|
280
|
+
|
|
281
|
+
function boot() {
|
|
282
|
+
try { init(); } catch (e) { console.error('[book]', e); }
|
|
283
|
+
}
|
|
284
|
+
})();
|