diff options
| author | Hsieh Chin Fan <pham@topo.tw> | 2024-09-24 00:21:24 +0800 |
|---|---|---|
| committer | Hsieh Chin Fan <pham@topo.tw> | 2024-09-24 00:40:50 +0800 |
| commit | 9b3af498b0b4ad4fa402927d545b0dfc001771d0 (patch) | |
| tree | 6ce223d09569be85790b119236d528d6ac80d5d0 | |
| parent | 6500301ce49107886315dd47d1f710ef1a3dc41d (diff) | |
feat: add mapCache for rendered map
* apply new config option: "render", just pass function to replace "use"
* check configList when render. If ID and config content are the same,
use cache otherwise
* remove CSS animation to prevent blinking when config changes very quick
* fix method about checking showcase is visible. This prevent reused map
gain focus.
| -rw-r--r-- | package.json | 2 | ||||
| -rw-r--r-- | src/css/dumbymap.css | 1 | ||||
| -rw-r--r-- | src/dumbymap.mjs | 35 |
3 files changed, 27 insertions, 11 deletions
diff --git a/package.json b/package.json index 63644ba..8ef7b2e 100644 --- a/package.json +++ b/package.json | |||
| @@ -50,7 +50,7 @@ | |||
| 50 | "dependencies": { | 50 | "dependencies": { |
| 51 | "easymde": "^2.18.0", | 51 | "easymde": "^2.18.0", |
| 52 | "leader-line": "^1.0.7", | 52 | "leader-line": "^1.0.7", |
| 53 | "mapclay": "^0.6.7", | 53 | "mapclay": "^0.7.0", |
| 54 | "markdown-it": "^14.1.0", | 54 | "markdown-it": "^14.1.0", |
| 55 | "markdown-it-anchor": "^9.2.0", | 55 | "markdown-it-anchor": "^9.2.0", |
| 56 | "markdown-it-footnote": "^4.0.0", | 56 | "markdown-it-footnote": "^4.0.0", |
diff --git a/src/css/dumbymap.css b/src/css/dumbymap.css index b9af75b..a2db479 100644 --- a/src/css/dumbymap.css +++ b/src/css/dumbymap.css | |||
| @@ -120,7 +120,6 @@ | |||
| 120 | border: 3px solid transparent; | 120 | border: 3px solid transparent; |
| 121 | 121 | ||
| 122 | background: white; | 122 | background: white; |
| 123 | animation: map-fade-in 1s; | ||
| 124 | 123 | ||
| 125 | &[data-focus="true"] { | 124 | &[data-focus="true"] { |
| 126 | border: 3px solid gray; | 125 | border: 3px solid gray; |
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 808ca06..01463c0 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs | |||
| @@ -16,6 +16,7 @@ const layouts = [ | |||
| 16 | new SideBySide({ name: "side-by-side" }), | 16 | new SideBySide({ name: "side-by-side" }), |
| 17 | new Overlay({ name: "overlay" }), | 17 | new Overlay({ name: "overlay" }), |
| 18 | ] | 18 | ] |
| 19 | const mapCache = {} | ||
| 19 | 20 | ||
| 20 | // FUNCTION: Get DocLinks from special anchor element {{{ | 21 | // FUNCTION: Get DocLinks from special anchor element {{{ |
| 21 | /** | 22 | /** |
| @@ -285,7 +286,11 @@ export const generateMaps = (container, callback) => { | |||
| 285 | const mutation = mutations.at(-1) | 286 | const mutation = mutations.at(-1) |
| 286 | const target = mutation.target | 287 | const target = mutation.target |
| 287 | const focus = target.getAttribute(mutation.attributeName) === 'true' | 288 | const focus = target.getAttribute(mutation.attributeName) === 'true' |
| 288 | const shouldBeInShowcase = focus && getComputedStyle(showcase).display !== 'none' | 289 | const shouldBeInShowcase = focus && showcase.checkVisibility({ |
| 290 | contentVisibilityAuto: true, | ||
| 291 | opacityProperty: true, | ||
| 292 | visibilityProperty: true, | ||
| 293 | }) | ||
| 289 | 294 | ||
| 290 | if (shouldBeInShowcase) { | 295 | if (shouldBeInShowcase) { |
| 291 | if (showcase.contains(target)) return | 296 | if (showcase.contains(target)) return |
| @@ -378,7 +383,9 @@ export const generateMaps = (container, callback) => { | |||
| 378 | //}}} | 383 | //}}} |
| 379 | // Render Maps {{{ | 384 | // Render Maps {{{ |
| 380 | 385 | ||
| 381 | const afterEachMapLoaded = (mapContainer) => { | 386 | const afterEachMapLoaded = (renderMap) => { |
| 387 | const mapContainer = renderMap.target | ||
| 388 | mapCache[mapContainer.id] = renderMap | ||
| 382 | mapContainer.setAttribute('tabindex', "-1") | 389 | mapContainer.setAttribute('tabindex', "-1") |
| 383 | mapContainer.setAttribute('data-state', "rendered") | 390 | mapContainer.setAttribute('data-state', "rendered") |
| 384 | 391 | ||
| @@ -410,7 +417,8 @@ export const generateMaps = (container, callback) => { | |||
| 410 | 417 | ||
| 411 | // Render each code block with "language-map" class | 418 | // Render each code block with "language-map" class |
| 412 | const elementsWithMapConfig = Array.from(container.querySelectorAll('pre:has(.language-map)') ?? []) | 419 | const elementsWithMapConfig = Array.from(container.querySelectorAll('pre:has(.language-map)') ?? []) |
| 413 | const render = renderWith(config => ({ | 420 | // Add default aliases into each config |
| 421 | const configConverter = (config => ({ | ||
| 414 | width: "100%", | 422 | width: "100%", |
| 415 | ...config, | 423 | ...config, |
| 416 | aliases: { | 424 | aliases: { |
| @@ -418,9 +426,10 @@ export const generateMaps = (container, callback) => { | |||
| 418 | ...config.aliases ?? {} | 426 | ...config.aliases ?? {} |
| 419 | }, | 427 | }, |
| 420 | })) | 428 | })) |
| 429 | const render = renderWith(configConverter) | ||
| 421 | elementsWithMapConfig | 430 | elementsWithMapConfig |
| 422 | .map(async (target) => { | 431 | .forEach(target => { |
| 423 | // Get text in code block starts with '```map' | 432 | // Get text in code block starts with markdown text '```map' |
| 424 | const configText = target.querySelector('.language-map') | 433 | const configText = target.querySelector('.language-map') |
| 425 | .textContent | 434 | .textContent |
| 426 | // BE CAREFUL!!! 0xa0 char is "non-breaking spaces" in HTML text content | 435 | // BE CAREFUL!!! 0xa0 char is "non-breaking spaces" in HTML text content |
| @@ -434,14 +443,22 @@ export const generateMaps = (container, callback) => { | |||
| 434 | console.warn('Fail to parse yaml config for element', target) | 443 | console.warn('Fail to parse yaml config for element', target) |
| 435 | } | 444 | } |
| 436 | 445 | ||
| 446 | // If map in cache has the same ID, and its config is the same, | ||
| 447 | // then don't render them again | ||
| 448 | configList.forEach(config => { | ||
| 449 | const cache = mapCache[config.id] | ||
| 450 | if (cache && JSON.stringify(cache.config) === JSON.stringify(configConverter(config))) { | ||
| 451 | target.appendChild(cache.target) | ||
| 452 | config.render = () => null | ||
| 453 | } | ||
| 454 | }) | ||
| 455 | |||
| 437 | // Render maps | 456 | // Render maps |
| 438 | return render(target, configList).map(renderMap => { | 457 | render(target, configList).forEach(renderMap => { |
| 439 | renderMaps.push(renderMap) | 458 | renderMaps.push(renderMap) |
| 440 | renderMap.promise | 459 | renderMap.promise |
| 441 | .then(_ => afterEachMapLoaded(renderMap.target)) | 460 | .then(_ => afterEachMapLoaded(renderMap)) |
| 442 | .catch(err => console.error('Fail to render target element with ID:', renderMap.target.id, err)) | 461 | .catch(err => console.error('Fail to render target element with ID:', renderMap.target.id, err)) |
| 443 | |||
| 444 | return renderMap.promise | ||
| 445 | }) | 462 | }) |
| 446 | }) | 463 | }) |
| 447 | 464 | ||