@abreen/tada 1.15.9 → 1.15.11
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/build/utils/code.ts +4 -4
- package/build/utils/katex.ts +37 -0
- package/build/utils/markdown.ts +2 -32
- package/build/utils/render.ts +2 -5
- package/init/content/lectures/01/Rectangle.java +2 -0
- package/package.json +1 -1
- package/src/index.ts +1 -1
- package/src/navigate/eligible.ts +8 -1
- package/src/page-update/index.ts +5 -1
- package/src/search/index.ts +105 -66
- package/src/top/index.ts +3 -2
- /package/src/{literate/style.scss → literate.scss} +0 -0
package/build/utils/code.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { getExtensionToShikiLanguage } from '../site-variables';
|
|
|
7
7
|
import { highlightCode } from './shiki-highlighter';
|
|
8
8
|
import externalLinksPlugin from '../external-links-plugin';
|
|
9
9
|
import { createApplyBasePath } from './paths';
|
|
10
|
+
import katexPlugin from './katex';
|
|
10
11
|
import { splitLines } from './literate-java';
|
|
11
12
|
import type { JavaTocEntry, SiteVariables } from '../types';
|
|
12
13
|
|
|
@@ -40,10 +41,9 @@ const log = makeLogger(import.meta.url);
|
|
|
40
41
|
const PROSE_LINE = /^\s*\/\/\/(\s|$)/;
|
|
41
42
|
|
|
42
43
|
function createCodeMarkdown(siteVariables: SiteVariables): MarkdownIt {
|
|
43
|
-
return new MarkdownIt({ html: true, typographer: true })
|
|
44
|
-
externalLinksPlugin,
|
|
45
|
-
|
|
46
|
-
);
|
|
44
|
+
return new MarkdownIt({ html: true, typographer: true })
|
|
45
|
+
.use(externalLinksPlugin, siteVariables)
|
|
46
|
+
.use(katexPlugin);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// Matches Markdown links: [text](url)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type MarkdownIt from 'markdown-it';
|
|
2
|
+
import Token from 'markdown-it/lib/token.mjs';
|
|
3
|
+
import markdownItKatex from '@vscode/markdown-it-katex';
|
|
4
|
+
import katex from 'katex';
|
|
5
|
+
import renderA11yString from 'katex/contrib/render-a11y-string';
|
|
6
|
+
|
|
7
|
+
export default function katexPlugin(markdown: MarkdownIt): void {
|
|
8
|
+
markdown.use(markdownItKatex);
|
|
9
|
+
|
|
10
|
+
// The @vscode/markdown-it-katex plugin's renderers swallow errors thrown
|
|
11
|
+
// by katex.renderToString() and return error HTML instead of propagating
|
|
12
|
+
// the exception. Override the renderers so parse errors fail the build.
|
|
13
|
+
// The plugin's tokenizer ($ and $$ delimiter parsing) is kept.
|
|
14
|
+
// Each renderer also adds an aria-label with a screen-reader-friendly
|
|
15
|
+
// description generated by katex/contrib/render-a11y-string.
|
|
16
|
+
markdown.renderer.rules.math_inline = (tokens: Token[], idx: number) => {
|
|
17
|
+
const latex = tokens[idx].content;
|
|
18
|
+
const html = katex.renderToString(latex, { throwOnError: true });
|
|
19
|
+
const a11y = markdown.utils.escapeHtml(renderA11yString(latex));
|
|
20
|
+
return html.replace(
|
|
21
|
+
'<span class="katex">',
|
|
22
|
+
`<span class="katex" aria-label="${a11y}">`,
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
const katexBlockRenderer = (tokens: Token[], idx: number) => {
|
|
26
|
+
const latex = tokens[idx].content;
|
|
27
|
+
const html = katex.renderToString(latex, {
|
|
28
|
+
throwOnError: true,
|
|
29
|
+
displayMode: true,
|
|
30
|
+
});
|
|
31
|
+
const a11y = markdown.utils.escapeHtml(renderA11yString(latex));
|
|
32
|
+
return `<p class="katex-block" aria-label="${a11y}">` + html + `</p>\n`;
|
|
33
|
+
};
|
|
34
|
+
markdown.renderer.rules.math_block = katexBlockRenderer;
|
|
35
|
+
markdown.renderer.rules.math_inline_block = katexBlockRenderer;
|
|
36
|
+
markdown.renderer.rules.math_inline_bare_block = katexBlockRenderer;
|
|
37
|
+
}
|
package/build/utils/markdown.ts
CHANGED
|
@@ -15,9 +15,7 @@ import deflistIdPlugin from '../deflist-id-plugin';
|
|
|
15
15
|
import externalLinksPlugin from '../external-links-plugin';
|
|
16
16
|
import { tocPlugin } from '../toc-plugin';
|
|
17
17
|
import columnsPlugin from '../columns-plugin';
|
|
18
|
-
import
|
|
19
|
-
import katex from 'katex';
|
|
20
|
-
import renderA11yString from 'katex/contrib/render-a11y-string';
|
|
18
|
+
import katexPlugin from './katex';
|
|
21
19
|
import markdownPartialsPlugin from './markdown-partials';
|
|
22
20
|
import type { RenderDependencyCollector, SiteVariables } from '../types';
|
|
23
21
|
|
|
@@ -81,7 +79,7 @@ export function createMarkdown(
|
|
|
81
79
|
.use(externalLinksPlugin, siteVariables)
|
|
82
80
|
.use(tocPlugin)
|
|
83
81
|
.use(columnsPlugin)
|
|
84
|
-
.use(
|
|
82
|
+
.use(katexPlugin)
|
|
85
83
|
.use(markdownItContainer, 'details', {
|
|
86
84
|
marker: '<',
|
|
87
85
|
validate: function (params: string) {
|
|
@@ -476,34 +474,6 @@ export function createMarkdown(
|
|
|
476
474
|
state.tokens = transformedTokens;
|
|
477
475
|
});
|
|
478
476
|
|
|
479
|
-
// The @vscode/markdown-it-katex plugin's renderers swallow errors thrown
|
|
480
|
-
// by katex.renderToString() and return error HTML instead of propagating
|
|
481
|
-
// the exception. Override the renderers so parse errors fail the build.
|
|
482
|
-
// The plugin's tokenizer ($ and $$ delimiter parsing) is kept.
|
|
483
|
-
// Each renderer also adds an aria-label with a screen-reader-friendly
|
|
484
|
-
// description generated by katex/contrib/render-a11y-string.
|
|
485
|
-
markdown.renderer.rules.math_inline = (tokens: Token[], idx: number) => {
|
|
486
|
-
const latex = tokens[idx].content;
|
|
487
|
-
const html = katex.renderToString(latex, { throwOnError: true });
|
|
488
|
-
const a11y = markdown.utils.escapeHtml(renderA11yString(latex));
|
|
489
|
-
return html.replace(
|
|
490
|
-
'<span class="katex">',
|
|
491
|
-
`<span class="katex" aria-label="${a11y}">`,
|
|
492
|
-
);
|
|
493
|
-
};
|
|
494
|
-
const katexBlockRenderer = (tokens: Token[], idx: number) => {
|
|
495
|
-
const latex = tokens[idx].content;
|
|
496
|
-
const html = katex.renderToString(latex, {
|
|
497
|
-
throwOnError: true,
|
|
498
|
-
displayMode: true,
|
|
499
|
-
});
|
|
500
|
-
const a11y = markdown.utils.escapeHtml(renderA11yString(latex));
|
|
501
|
-
return `<p class="katex-block" aria-label="${a11y}">` + html + `</p>\n`;
|
|
502
|
-
};
|
|
503
|
-
markdown.renderer.rules.math_block = katexBlockRenderer;
|
|
504
|
-
markdown.renderer.rules.math_inline_block = katexBlockRenderer;
|
|
505
|
-
markdown.renderer.rules.math_inline_bare_block = katexBlockRenderer;
|
|
506
|
-
|
|
507
477
|
const usedIds = new Map<string, number>();
|
|
508
478
|
markdown.use(markdownItContainer, 'alert', {
|
|
509
479
|
marker: '!',
|
package/build/utils/render.ts
CHANGED
|
@@ -359,13 +359,10 @@ export function renderCodePageAsset({
|
|
|
359
359
|
isWatchMode: isWatchMode(assetFiles),
|
|
360
360
|
});
|
|
361
361
|
|
|
362
|
+
const templateHtml = render('code.html', templateParameters) as string;
|
|
362
363
|
const finalized = finalizeHtmlPage({
|
|
363
364
|
filePath,
|
|
364
|
-
html:
|
|
365
|
-
render('code.html', templateParameters) as string,
|
|
366
|
-
assetFiles,
|
|
367
|
-
distDir,
|
|
368
|
-
),
|
|
365
|
+
html: preparePageTemplateHtml({ templateHtml, assetFiles, distDir }),
|
|
369
366
|
siteVariables,
|
|
370
367
|
sourceUrlPath,
|
|
371
368
|
validInternalTargets,
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
/// See [`rectangle.py`](./rectangle.py) for a Python version of this class.
|
|
7
7
|
///
|
|
8
8
|
/// Here's `vars.foobar`: <%= vars.foobar %>
|
|
9
|
+
///
|
|
10
|
+
/// Here's some LaTeX: $\frac{n(n-1)}{2}$ is $O(n^2)$
|
|
9
11
|
public class Rectangle {
|
|
10
12
|
private int width;
|
|
11
13
|
private int height;
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
package/src/navigate/eligible.ts
CHANGED
|
@@ -45,7 +45,14 @@ export function isEligibleLink(
|
|
|
45
45
|
return false;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
const normalizedBasePath = basePath.endsWith('/')
|
|
49
|
+
? basePath.slice(0, -1) || '/'
|
|
50
|
+
: basePath;
|
|
51
|
+
if (
|
|
52
|
+
normalizedBasePath !== '/' &&
|
|
53
|
+
url.pathname !== normalizedBasePath &&
|
|
54
|
+
!url.pathname.startsWith(`${normalizedBasePath}/`)
|
|
55
|
+
) {
|
|
49
56
|
return false;
|
|
50
57
|
}
|
|
51
58
|
|
package/src/page-update/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { NAVIGATION_EVENT, refreshCurrentPage } from '../navigate/runtime';
|
|
|
10
10
|
import { globals } from '../globals';
|
|
11
11
|
|
|
12
12
|
const POLL_INTERVAL_MS = 600_000;
|
|
13
|
+
export const PAGE_UPDATE_REFRESH_EVENT = 'tada:page-update-refresh';
|
|
13
14
|
|
|
14
15
|
interface PageUpdateOptions {
|
|
15
16
|
pollIntervalMs?: number;
|
|
@@ -247,7 +248,10 @@ export function mountPageUpdate(
|
|
|
247
248
|
}
|
|
248
249
|
|
|
249
250
|
function handleReloadClick() {
|
|
250
|
-
void refreshPage(window)
|
|
251
|
+
void refreshPage(window).then(() => {
|
|
252
|
+
const EventCtor = (window as unknown as { Event: typeof Event }).Event;
|
|
253
|
+
window.dispatchEvent(new EventCtor(PAGE_UPDATE_REFRESH_EVENT));
|
|
254
|
+
});
|
|
251
255
|
}
|
|
252
256
|
|
|
253
257
|
reloadButton.addEventListener('click', handleReloadClick);
|
package/src/search/index.ts
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import { getElement, applyBasePath } from '../util';
|
|
2
2
|
import { getPdfPageNumber, groupPdfResults } from './pdf-utils';
|
|
3
3
|
import type { Result } from './pdf-utils';
|
|
4
|
-
import {
|
|
5
|
-
getResponseValidators,
|
|
6
|
-
hasResponseValidatorsChanged,
|
|
7
|
-
type ResponseValidators,
|
|
8
|
-
} from '../validators';
|
|
4
|
+
import { PAGE_UPDATE_REFRESH_EVENT } from '../page-update';
|
|
9
5
|
import { globals } from '../globals';
|
|
10
6
|
|
|
11
|
-
const MAX_RESULTS = 24;
|
|
12
|
-
|
|
13
7
|
interface PagefindSubResult {
|
|
14
8
|
title?: string;
|
|
15
9
|
url: string;
|
|
@@ -34,7 +28,9 @@ interface PagefindSearchResult {
|
|
|
34
28
|
}
|
|
35
29
|
|
|
36
30
|
interface Pagefind {
|
|
31
|
+
destroy(): Promise<void>;
|
|
37
32
|
init(): Promise<void>;
|
|
33
|
+
options(options: { basePath: string }): Promise<void>;
|
|
38
34
|
search(query: string): Promise<{ results: PagefindSearchResult[] }>;
|
|
39
35
|
}
|
|
40
36
|
|
|
@@ -61,8 +57,7 @@ async function doSearch(query: string, window: Window): Promise<SearchState> {
|
|
|
61
57
|
}
|
|
62
58
|
|
|
63
59
|
const search = await pagefind.search(query);
|
|
64
|
-
const
|
|
65
|
-
const data = await Promise.all(slice.map(r => r.data()));
|
|
60
|
+
const data = await Promise.all(search.results.map(r => r.data()));
|
|
66
61
|
|
|
67
62
|
const titlePostfix = __SITE_TITLE_POSTFIX__;
|
|
68
63
|
const results: Result[] = data.map((d: PagefindResult) => {
|
|
@@ -139,9 +134,9 @@ function render(
|
|
|
139
134
|
ol.tabIndex = -1;
|
|
140
135
|
ol.setAttribute('aria-label', 'Search results');
|
|
141
136
|
|
|
142
|
-
const totalVisible =
|
|
137
|
+
const totalVisible = state.results.length;
|
|
143
138
|
|
|
144
|
-
state.results.
|
|
139
|
+
state.results.forEach((result, i) => {
|
|
145
140
|
const a = doc.createElement('a');
|
|
146
141
|
a.id = `result-${i}`;
|
|
147
142
|
a.className = 'result';
|
|
@@ -175,7 +170,7 @@ function render(
|
|
|
175
170
|
li.setAttribute('aria-labelledby', `title-${i}`);
|
|
176
171
|
li.appendChild(a);
|
|
177
172
|
|
|
178
|
-
const subsToShow = result.subResults
|
|
173
|
+
const subsToShow = result.subResults;
|
|
179
174
|
if (subsToShow.length > 0) {
|
|
180
175
|
const subList = doc.createElement('ul');
|
|
181
176
|
subList.className = 'sub-results';
|
|
@@ -250,10 +245,8 @@ function render(
|
|
|
250
245
|
countSpan.textContent = 'No results';
|
|
251
246
|
} else if (n === 1) {
|
|
252
247
|
countSpan.textContent = 'One result';
|
|
253
|
-
} else if (n <= MAX_RESULTS) {
|
|
254
|
-
countSpan.textContent = `${n} results`;
|
|
255
248
|
} else {
|
|
256
|
-
countSpan.textContent =
|
|
249
|
+
countSpan.textContent = `${n} results`;
|
|
257
250
|
}
|
|
258
251
|
}
|
|
259
252
|
|
|
@@ -286,64 +279,56 @@ export default (window: Window) => {
|
|
|
286
279
|
// Unhide (hidden via inline style in template to prevent FOUC)
|
|
287
280
|
resultsDiv.style.display = '';
|
|
288
281
|
|
|
289
|
-
let
|
|
290
|
-
let
|
|
291
|
-
let indexCheckInFlight = false;
|
|
292
|
-
|
|
293
|
-
async function loadPagefind() {
|
|
294
|
-
if (pagefind) {
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
pagefind = (await globals.importModule(
|
|
299
|
-
applyBasePath('/pagefind/pagefind.js'),
|
|
300
|
-
)) as Pagefind;
|
|
301
|
-
|
|
302
|
-
await pagefind.init();
|
|
282
|
+
let pagefindLoadPromise: Promise<boolean> | null = null;
|
|
283
|
+
let pagefindLoadGeneration = 0;
|
|
303
284
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
if (res.ok) {
|
|
310
|
-
entryValidators = getResponseValidators(res);
|
|
285
|
+
function pagefindModulePath(generation: number) {
|
|
286
|
+
const path = applyBasePath('/pagefind/pagefind.js');
|
|
287
|
+
if (generation === 0) {
|
|
288
|
+
return path;
|
|
311
289
|
}
|
|
290
|
+
return `${path}?tada-pagefind-refresh=${generation}`;
|
|
312
291
|
}
|
|
313
292
|
|
|
314
|
-
async function
|
|
315
|
-
if (
|
|
316
|
-
return;
|
|
293
|
+
async function loadPagefind(): Promise<boolean> {
|
|
294
|
+
if (pagefind) {
|
|
295
|
+
return true;
|
|
317
296
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
if (
|
|
326
|
-
return;
|
|
297
|
+
|
|
298
|
+
const generation = pagefindLoadGeneration;
|
|
299
|
+
pagefindLoadPromise ??= (async () => {
|
|
300
|
+
const loadedPagefind = (await globals.importModule(
|
|
301
|
+
pagefindModulePath(generation),
|
|
302
|
+
)) as Pagefind;
|
|
303
|
+
|
|
304
|
+
if (generation !== pagefindLoadGeneration) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
if (generation > 0) {
|
|
308
|
+
await loadedPagefind.options({ basePath: applyBasePath('/pagefind/') });
|
|
327
309
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
invalidateUpdates();
|
|
331
|
-
pagefind = null;
|
|
332
|
-
await loadPagefind();
|
|
333
|
-
const updateId = ++latestUpdateId;
|
|
334
|
-
await update(updateId);
|
|
310
|
+
if (generation !== pagefindLoadGeneration) {
|
|
311
|
+
return false;
|
|
335
312
|
}
|
|
336
|
-
|
|
337
|
-
|
|
313
|
+
await loadedPagefind.init();
|
|
314
|
+
if (generation !== pagefindLoadGeneration) {
|
|
315
|
+
await loadedPagefind.destroy();
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
pagefind = loadedPagefind;
|
|
319
|
+
return true;
|
|
320
|
+
})();
|
|
321
|
+
|
|
322
|
+
const promise = pagefindLoadPromise;
|
|
323
|
+
try {
|
|
324
|
+
return await promise;
|
|
338
325
|
} finally {
|
|
339
|
-
|
|
326
|
+
if (pagefindLoadPromise === promise) {
|
|
327
|
+
pagefindLoadPromise = null;
|
|
328
|
+
}
|
|
340
329
|
}
|
|
341
330
|
}
|
|
342
331
|
|
|
343
|
-
loadPagefind().catch(err => {
|
|
344
|
-
console.log(`failed to load Pagefind: ${err}`);
|
|
345
|
-
});
|
|
346
|
-
|
|
347
332
|
const state: State = {
|
|
348
333
|
value: '',
|
|
349
334
|
showResults: false,
|
|
@@ -362,10 +347,11 @@ export default (window: Window) => {
|
|
|
362
347
|
if (updateId !== latestUpdateId) {
|
|
363
348
|
return;
|
|
364
349
|
}
|
|
365
|
-
if (nextState) {
|
|
366
|
-
|
|
367
|
-
state.totalResults = nextState.totalResults;
|
|
350
|
+
if (!nextState) {
|
|
351
|
+
return;
|
|
368
352
|
}
|
|
353
|
+
state.results = nextState.results;
|
|
354
|
+
state.totalResults = nextState.totalResults;
|
|
369
355
|
if (!state.showResults) {
|
|
370
356
|
return;
|
|
371
357
|
}
|
|
@@ -381,6 +367,55 @@ export default (window: Window) => {
|
|
|
381
367
|
latestUpdateId += 1;
|
|
382
368
|
}
|
|
383
369
|
|
|
370
|
+
function loadPagefindAndUpdate() {
|
|
371
|
+
loadPagefind()
|
|
372
|
+
.then(loadedCurrentPagefind => {
|
|
373
|
+
if (loadedCurrentPagefind && state.showResults) {
|
|
374
|
+
queueUpdate();
|
|
375
|
+
}
|
|
376
|
+
})
|
|
377
|
+
.catch(err => {
|
|
378
|
+
console.log(`failed to load Pagefind: ${err}`);
|
|
379
|
+
if (state.showResults) {
|
|
380
|
+
render(input!, resultsContainer, state, false);
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function invalidatePagefind() {
|
|
386
|
+
pagefindLoadGeneration += 1;
|
|
387
|
+
pagefind = null;
|
|
388
|
+
pagefindLoadPromise = null;
|
|
389
|
+
invalidateUpdates();
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
async function reloadPagefindAfterPageUpdateRefresh() {
|
|
393
|
+
const stalePagefind = pagefind;
|
|
394
|
+
invalidatePagefind();
|
|
395
|
+
if (state.showResults) {
|
|
396
|
+
render(input!, resultsContainer, state, true);
|
|
397
|
+
}
|
|
398
|
+
if (stalePagefind) {
|
|
399
|
+
try {
|
|
400
|
+
await stalePagefind.destroy();
|
|
401
|
+
} catch (err) {
|
|
402
|
+
console.log(`failed to destroy Pagefind: ${err}`);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
loadPagefindAndUpdate();
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function handlePageUpdateRefresh() {
|
|
409
|
+
reloadPagefindAfterPageUpdateRefresh().catch(err => {
|
|
410
|
+
console.log(`failed to reload Pagefind: ${err}`);
|
|
411
|
+
if (state.showResults) {
|
|
412
|
+
render(input!, resultsContainer, state, false);
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
loadPagefindAndUpdate();
|
|
418
|
+
|
|
384
419
|
function hide() {
|
|
385
420
|
if (!state.showResults) {
|
|
386
421
|
return;
|
|
@@ -417,7 +452,6 @@ export default (window: Window) => {
|
|
|
417
452
|
if (previous && !resultsContainer.contains(previous)) {
|
|
418
453
|
previousFocus = previous;
|
|
419
454
|
}
|
|
420
|
-
checkForIndexUpdate().catch(() => {});
|
|
421
455
|
if (!state.showResults) {
|
|
422
456
|
state.showResults = true;
|
|
423
457
|
queueUpdate();
|
|
@@ -563,8 +597,13 @@ export default (window: Window) => {
|
|
|
563
597
|
window.addEventListener('pointerdown', handleWindowPointerDown);
|
|
564
598
|
window.addEventListener('pointermove', handleWindowPointerMove);
|
|
565
599
|
window.addEventListener('keydown', handleWindowKeyDown);
|
|
600
|
+
window.addEventListener(PAGE_UPDATE_REFRESH_EVENT, handlePageUpdateRefresh);
|
|
566
601
|
|
|
567
602
|
return () => {
|
|
603
|
+
window.removeEventListener(
|
|
604
|
+
PAGE_UPDATE_REFRESH_EVENT,
|
|
605
|
+
handlePageUpdateRefresh,
|
|
606
|
+
);
|
|
568
607
|
window.removeEventListener('keydown', handleWindowKeyDown);
|
|
569
608
|
window.removeEventListener('pointermove', handleWindowPointerMove);
|
|
570
609
|
window.removeEventListener('pointerdown', handleWindowPointerDown);
|
package/src/top/index.ts
CHANGED
|
@@ -30,11 +30,12 @@ export default (window: Window) => {
|
|
|
30
30
|
link.onclick = e => {
|
|
31
31
|
e.preventDefault();
|
|
32
32
|
const cleanUrl = window.location.pathname + window.location.search;
|
|
33
|
+
const historyState = window.history.state;
|
|
33
34
|
if (window.location.hash) {
|
|
34
35
|
globals.setLocationHash(window, '');
|
|
35
|
-
window.history.replaceState(
|
|
36
|
+
window.history.replaceState(historyState, '', cleanUrl);
|
|
36
37
|
} else {
|
|
37
|
-
window.history.replaceState(
|
|
38
|
+
window.history.replaceState(historyState, '', cleanUrl);
|
|
38
39
|
}
|
|
39
40
|
window.scrollTo({ top: 0 });
|
|
40
41
|
const toc = window.document.querySelector('nav.toc') as HTMLElement | null;
|
|
File without changes
|