diff options
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | src/css/dumbymap.css | 42 | ||||
-rw-r--r-- | src/dumbymap.mjs | 42 |
3 files changed, 75 insertions, 11 deletions
diff --git a/package.json b/package.json index 0204eed..6af2368 100644 --- a/package.json +++ b/package.json | |||
@@ -51,7 +51,7 @@ | |||
51 | "dependencies": { | 51 | "dependencies": { |
52 | "easymde": "^2.18.0", | 52 | "easymde": "^2.18.0", |
53 | "leader-line": "^1.0.7", | 53 | "leader-line": "^1.0.7", |
54 | "mapclay": "^0.8.2", | 54 | "mapclay": "^0.8.3", |
55 | "markdown-it": "^14.1.0", | 55 | "markdown-it": "^14.1.0", |
56 | "markdown-it-anchor": "^9.2.0", | 56 | "markdown-it-anchor": "^9.2.0", |
57 | "markdown-it-footnote": "^4.0.0", | 57 | "markdown-it-footnote": "^4.0.0", |
diff --git a/src/css/dumbymap.css b/src/css/dumbymap.css index 7b7f393..c6782fc 100644 --- a/src/css/dumbymap.css +++ b/src/css/dumbymap.css | |||
@@ -52,6 +52,8 @@ root { | |||
52 | position: relative; | 52 | position: relative; |
53 | transform-origin: top left; | 53 | transform-origin: top left; |
54 | 54 | ||
55 | transition: flex-basis 300ms ease-in-out; | ||
56 | |||
55 | &.focus::after { | 57 | &.focus::after { |
56 | content: 'Map-ID: ' attr(id); | 58 | content: 'Map-ID: ' attr(id); |
57 | padding: 0.3rem 0.5rem; | 59 | padding: 0.3rem 0.5rem; |
@@ -75,18 +77,52 @@ root { | |||
75 | opacity: 0; | 77 | opacity: 0; |
76 | animation: 1.5s forwards fade-out cubic-bezier(0.44, 0.18, 0.86, -0.21); | 78 | animation: 1.5s forwards fade-out cubic-bezier(0.44, 0.18, 0.86, -0.21); |
77 | } | 79 | } |
80 | |||
81 | &[data-report*='/'] { | ||
82 | &::after { | ||
83 | content: attr(data-report); | ||
84 | padding: 0.3rem 0.5rem; | ||
85 | |||
86 | position: absolute; | ||
87 | left: 50%; | ||
88 | top: 50%; | ||
89 | z-index: 9999; | ||
90 | |||
91 | border: solid transparent; | ||
92 | border-radius: 5px; | ||
93 | |||
94 | background: gray; | ||
95 | |||
96 | color: white; | ||
97 | font-size: 1.5rem; | ||
98 | font-weight: bold; | ||
99 | line-height: 1.2; | ||
100 | |||
101 | transform: translate(-50%, -50%); | ||
102 | } | ||
103 | |||
104 | &[data-render='fulfilled'][data-report$="\20"]::after { | ||
105 | content: '\2714 ' attr(data-report); | ||
106 | animation: 1.5s forwards fade-out cubic-bezier(0.44, 0.18, 0.86, -0.21); | ||
107 | } | ||
108 | |||
109 | &[data-render='unfulfilled'][data-report$="\20"]::after { | ||
110 | content: '\2716 ' attr(data-report); | ||
111 | animation: 2.5s forwards fade-out cubic-bezier(0.44, 0.18, 0.86, -0.21); | ||
112 | } | ||
113 | } | ||
78 | } | 114 | } |
79 | 115 | ||
80 | .with-leader-line:not(:has(> *)) { | 116 | .with-leader-line:not(:has(> *)) { |
81 | display: inline-block; | 117 | display: inline-block; |
118 | padding-right: 15px; | ||
119 | padding-left: 6px; | ||
82 | 120 | ||
83 | background-image: url('data:image/svg+xml;charset=utf-8;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij48cG9seWdvbiBwb2ludHM9IjI0LDAgMCw4IDgsMTEgMCwxOSA1LDI0IDEzLDE2IDE2LDI0IiBmaWxsPSJjb3JhbCIvPjwvc3ZnPg=='); | 121 | background-image: url('data:image/svg+xml;charset=utf-8;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij48cG9seWdvbiBwb2ludHM9IjI0LDAgMCw4IDgsMTEgMCwxOSA1LDI0IDEzLDE2IDE2LDI0IiBmaWxsPSJjb3JhbCIvPjwvc3ZnPg=='); |
84 | background-repeat: no-repeat; | 122 | background-repeat: no-repeat; |
85 | background-position: right 2px top 2px; | 123 | background-position: right 2px top 2px; |
86 | 124 | ||
87 | color: #555; | 125 | color: #555; |
88 | padding-right: 15px; | ||
89 | padding-left: 6px; | ||
90 | background-size: 12px 12px; | 126 | background-size: 12px 12px; |
91 | 127 | ||
92 | &.geolink { | 128 | &.geolink { |
@@ -219,9 +255,9 @@ root { | |||
219 | .SemanticHtml { | 255 | .SemanticHtml { |
220 | display: flex; | 256 | display: flex; |
221 | flex-direction: column; | 257 | flex-direction: column; |
258 | justify-content: flex-start; | ||
222 | height: 100%; | 259 | height: 100%; |
223 | gap: 1rem; | 260 | gap: 1rem; |
224 | justify-content: flex-start; | ||
225 | overflow-y: auto; | 261 | overflow-y: auto; |
226 | 262 | ||
227 | /* Trivial: gray out text not focused */ | 263 | /* Trivial: gray out text not focused */ |
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index cb029de..241c6b9 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs | |||
@@ -426,19 +426,47 @@ export const generateMaps = (container, { delay, mapCallback }) => { | |||
426 | 426 | ||
427 | // Render each code block with "language-map" class | 427 | // Render each code block with "language-map" class |
428 | const elementsWithMapConfig = Array.from( | 428 | const elementsWithMapConfig = Array.from( |
429 | container.querySelectorAll("pre:has(.language-map)") ?? [], | 429 | container.querySelectorAll('pre:has(.language-map)') ?? [] |
430 | ); | 430 | ) |
431 | // Add default aliases into each config | 431 | /** |
432 | * updateAttributeByStep. | ||
433 | * | ||
434 | * @param {Object} -- renderer which is running steps | ||
435 | */ | ||
436 | const updateAttributeByStep = ({ results, target, steps }) => { | ||
437 | let passNum = results | ||
438 | .filter(r => r.type === 'step' && r.state.match(/success|skip/)) | ||
439 | .length | ||
440 | const total = steps.length; | ||
441 | passNum += `/${total}`; | ||
442 | if (results.filter(r=>r.type === 'step').length === total) { | ||
443 | passNum += '\u0020' | ||
444 | } | ||
445 | |||
446 | // FIXME HACK use MutationObserver for animation | ||
447 | if (!target.animations) target.animations = Promise.resolve(); | ||
448 | target.animations = target.animations.then(async () => { | ||
449 | await new Promise(resolve => setTimeout(resolve, 150)); | ||
450 | target.setAttribute('data-report', passNum); | ||
451 | }); | ||
452 | } | ||
453 | /** | ||
454 | * config converter for mapclay.renderWith() | ||
455 | * | ||
456 | * @param {Object} config | ||
457 | * @return {Object} -- converted config | ||
458 | */ | ||
432 | const configConverter = config => ({ | 459 | const configConverter = config => ({ |
433 | use: config.use ?? "Leaflet", | 460 | use: config.use ?? 'Leaflet', |
434 | width: "100%", | 461 | width: '100%', |
435 | ...config, | 462 | ...config, |
436 | aliases: { | 463 | aliases: { |
437 | ...defaultAliases, | 464 | ...defaultAliases, |
438 | ...(config.aliases ?? {}), | 465 | ...(config.aliases ?? {}), |
439 | }, | 466 | }, |
440 | }); | 467 | stepCallback: updateAttributeByStep, |
441 | const render = renderWith(configConverter); | 468 | }) |
469 | const render = renderWith(configConverter) | ||
442 | elementsWithMapConfig.forEach(target => { | 470 | elementsWithMapConfig.forEach(target => { |
443 | // Get text in code block starts with markdown text '```map' | 471 | // Get text in code block starts with markdown text '```map' |
444 | const configText = target | 472 | const configText = target |