aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/dumbymap.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'src/dumbymap.mjs')
-rw-r--r--src/dumbymap.mjs68
1 files changed, 38 insertions, 30 deletions
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs
index b02e783..180517b 100644
--- a/src/dumbymap.mjs
+++ b/src/dumbymap.mjs
@@ -10,15 +10,19 @@ import * as utils from './dumbyUtils'
10import * as menuItem from './MenuItem' 10import * as menuItem from './MenuItem'
11import PlainModal from 'plain-modal' 11import PlainModal from 'plain-modal'
12 12
13/** Selector of special HTML Elements */
13const mapBlockSelector = 'pre:has(.language-map)' 14const mapBlockSelector = 'pre:has(.language-map)'
14const docLinkSelector = 'a[href^="#"][title^="=>"]' 15const docLinkSelector = 'a[href^="#"][title^="=>"]'
15const geoLinkSelector = 'a[href^="geo:"]' 16const geoLinkSelector = 'a[href^="geo:"]'
16 17
18/** Default Layouts */
17const layouts = [ 19const layouts = [
18 new Layout({ name: 'normal' }), 20 new Layout({ name: 'normal' }),
19 new SideBySide({ name: 'side-by-side' }), 21 new SideBySide({ name: 'side-by-side' }),
20 new Overlay({ name: 'overlay' }), 22 new Overlay({ name: 'overlay' }),
21] 23]
24
25/** Cache across every dumbymap generation */
22const mapCache = {} 26const mapCache = {}
23 27
24/** 28/**
@@ -28,12 +32,12 @@ const mapCache = {}
28 * @param {String} mdContent -- Texts in Markdown 32 * @param {String} mdContent -- Texts in Markdown
29 */ 33 */
30export const markdown2HTML = (container, mdContent) => { 34export const markdown2HTML = (container, mdContent) => {
31 // Render: Markdown -> HTML {{{ 35 /** Prepare Elements for Container */
32 container.replaceChildren() 36 container.replaceChildren()
33
34 container.innerHTML = '<div class="SemanticHtml"></div>' 37 container.innerHTML = '<div class="SemanticHtml"></div>'
35 const htmlHolder = container.querySelector('.SemanticHtml') 38 const htmlHolder = container.querySelector('.SemanticHtml')
36 39
40 /** Prepare MarkdownIt Instance */
37 const md = MarkdownIt({ 41 const md = MarkdownIt({
38 html: true, 42 html: true,
39 breaks: true, 43 breaks: true,
@@ -48,11 +52,11 @@ export const markdown2HTML = (container, mdContent) => {
48 .use(MarkdownItFrontMatter) 52 .use(MarkdownItFrontMatter)
49 .use(MarkdownItInjectLinenumbers) 53 .use(MarkdownItInjectLinenumbers)
50 54
51 // Create links with geo scheme 55 /** Set up linkify for GeoLinks */
52 const coordinateRegex = /^(\D*)(-?\d+\.?\d*)\s*([,\x2F\uFF0C])\s*(-?\d+\.?\d*)/ 56 const coordinateRegex = /^(\D*)(-?\d+\.?\d*)\s*([,\x2F\uFF0C])\s*(-?\d+\.?\d*)/
53 const coordinateValue = { 57 const coordinateValue = {
54 validate: coordinateRegex, 58 validate: coordinateRegex,
55 normalize: function (match) { 59 normalize: function(match) {
56 const [, , x, sep, y] = match.text.match(coordinateRegex) 60 const [, , x, sep, y] = match.text.match(coordinateRegex)
57 match.url = `geo:${y},${x}?xy=${x},${y}` 61 match.url = `geo:${y},${x}?xy=${x},${y}`
58 match.text = `${x}${sep} ${y}` 62 match.text = `${x}${sep} ${y}`
@@ -65,6 +69,7 @@ export const markdown2HTML = (container, mdContent) => {
65 md.linkify.add(prefix, coordinateValue), 69 md.linkify.add(prefix, coordinateValue),
66 ) 70 )
67 71
72 /** Custom rule for Blocks in DumbyMap */
68 // FIXME A better way to generate blocks 73 // FIXME A better way to generate blocks
69 md.renderer.rules.dumby_block_open = () => '<div>' 74 md.renderer.rules.dumby_block_open = () => '<div>'
70 md.renderer.rules.dumby_block_close = () => '</div>' 75 md.renderer.rules.dumby_block_close = () => '</div>'
@@ -87,8 +92,9 @@ export const markdown2HTML = (container, mdContent) => {
87 state.tokens.push(new state.Token('dumby_block_close', '', -1)) 92 state.tokens.push(new state.Token('dumby_block_close', '', -1))
88 }) 93 })
89 94
95 /** Render HTML */
90 htmlHolder.innerHTML = md.render(mdContent) 96 htmlHolder.innerHTML = md.render(mdContent)
91 97 /** Post HTML rendered */
92 // TODO Do this in markdown-it 98 // TODO Do this in markdown-it
93 const blocks = htmlHolder.querySelectorAll(':scope > div:not(:has(nav))') 99 const blocks = htmlHolder.querySelectorAll(':scope > div:not(:has(nav))')
94 blocks.forEach(b => { 100 blocks.forEach(b => {
@@ -97,7 +103,6 @@ export const markdown2HTML = (container, mdContent) => {
97 }) 103 })
98 104
99 return container 105 return container
100 // }}}
101} 106}
102 107
103/** 108/**
@@ -108,6 +113,8 @@ export const markdown2HTML = (container, mdContent) => {
108 * @return {Object} dumbymap -- Include and Elements and Methods about managing contents 113 * @return {Object} dumbymap -- Include and Elements and Methods about managing contents
109 */ 114 */
110export const generateMaps = (container, { delay, renderCallback } = {}) => { 115export const generateMaps = (container, { delay, renderCallback } = {}) => {
116
117 /** Prepare Contaner/HTML Holder/Showcase */
111 container.classList.add('Dumby') 118 container.classList.add('Dumby')
112 container.removeAttribute('data-layout') 119 container.removeAttribute('data-layout')
113 container.setAttribute('data-layout', layouts[0].name) 120 container.setAttribute('data-layout', layouts[0].name)
@@ -117,10 +124,13 @@ export const generateMaps = (container, { delay, renderCallback } = {}) => {
117 container.appendChild(showcase) 124 container.appendChild(showcase)
118 showcase.classList.add('Showcase') 125 showcase.classList.add('Showcase')
119 const renderPromises = [] 126 const renderPromises = []
127
128 /** Prepare Modal */
120 const modalContent = document.createElement('div') 129 const modalContent = document.createElement('div')
121 container.appendChild(modalContent) 130 container.appendChild(modalContent)
122 const modal = new PlainModal(modalContent) 131 const modal = new PlainModal(modalContent)
123 132
133 /** Define dumbymap Object */
124 const dumbymap = { 134 const dumbymap = {
125 layouts, 135 layouts,
126 container, 136 container,
@@ -152,21 +162,16 @@ export const generateMaps = (container, { delay, renderCallback } = {}) => {
152 dumbymap.utils[util] = func.bind(dumbymap) 162 dumbymap.utils[util] = func.bind(dumbymap)
153 }) 163 })
154 164
155 // LeaderLine {{{ 165 /** Create GeoLinks and DocLinks */
156 166 container.querySelectorAll(docLinkSelector)
157 Array.from(container.querySelectorAll(docLinkSelector)).filter( 167 .forEach(utils.createDocLink)
158 utils.createDocLink,
159 )
160
161 // Add GeoLinks
162 container.querySelectorAll(geoLinkSelector) 168 container.querySelectorAll(geoLinkSelector)
163 .forEach(utils.createGeoLink) 169 .forEach(utils.createGeoLink)
164 170
165 // }}} 171 /**
166 // CSS observer {{{ 172 * mapFocusObserver. observe for map focus
167 // Focus Map {{{ 173 * @return {MutationObserver} observer
168 // Set focusArea 174 */
169
170 const mapFocusObserver = () => 175 const mapFocusObserver = () =>
171 new window.MutationObserver(mutations => { 176 new window.MutationObserver(mutations => {
172 const mutation = mutations.at(-1) 177 const mutation = mutations.at(-1)
@@ -238,11 +243,8 @@ export const generateMaps = (container, { delay, renderCallback } = {}) => {
238 }).finished.finally(afterAnimation) 243 }).finished.finally(afterAnimation)
239 } 244 }
240 }) 245 })
241 // }}}
242 // Layout {{{
243 // press key to switch layout
244 246
245 // observe layout change 247 /** Observer for layout changes */
246 const layoutObserver = new window.MutationObserver(mutations => { 248 const layoutObserver = new window.MutationObserver(mutations => {
247 const mutation = mutations.at(-1) 249 const mutation = mutations.at(-1)
248 const oldLayout = mutation.oldValue 250 const oldLayout = mutation.oldValue
@@ -281,10 +283,12 @@ export const generateMaps = (container, { delay, renderCallback } = {}) => {
281 }) 283 })
282 284
283 onRemove(htmlHolder, () => layoutObserver.disconnect()) 285 onRemove(htmlHolder, () => layoutObserver.disconnect())
284 // }}}
285 // }}}
286 // Render Maps {{{
287 286
287 /**
288 * afterMapRendered. callback of each map rendered
289 *
290 * @param {Object} renderer
291 */
288 const afterMapRendered = renderer => { 292 const afterMapRendered = renderer => {
289 const mapElement = renderer.target 293 const mapElement = renderer.target
290 // FIXME 294 // FIXME
@@ -371,7 +375,11 @@ export const generateMaps = (container, { delay, renderCallback } = {}) => {
371 }, 375 },
372 stepCallback: updateAttributeByStep, 376 stepCallback: updateAttributeByStep,
373 }) 377 })
378
379 /** Get render method by converter */
374 const render = renderWith(configConverter) 380 const render = renderWith(configConverter)
381
382 /** Render each taget element for maps */
375 let order = 0 383 let order = 0
376 elementsWithMapConfig.forEach(target => { 384 elementsWithMapConfig.forEach(target => {
377 // Get text in code block starts with markdown text '```map' 385 // Get text in code block starts with markdown text '```map'
@@ -428,8 +436,8 @@ export const generateMaps = (container, { delay, renderCallback } = {}) => {
428 clearTimeout(timer) 436 clearTimeout(timer)
429 }) 437 })
430 }) 438 })
431 // }}} 439
432 // Menu {{{ 440 /** Prepare Context Menu */
433 const menu = document.createElement('div') 441 const menu = document.createElement('div')
434 menu.className = 'menu' 442 menu.className = 'menu'
435 menu.style.display = 'none' 443 menu.style.display = 'none'
@@ -441,7 +449,7 @@ export const generateMaps = (container, { delay, renderCallback } = {}) => {
441 } 449 }
442 container.appendChild(menu) 450 container.appendChild(menu)
443 451
444 // Menu Items 452 /** Menu Items for Context Menu */
445 container.oncontextmenu = e => { 453 container.oncontextmenu = e => {
446 menu.replaceChildren() 454 menu.replaceChildren()
447 menu.style.display = 'block' 455 menu.style.display = 'block'
@@ -479,7 +487,7 @@ export const generateMaps = (container, { delay, renderCallback } = {}) => {
479 return menu 487 return menu
480 } 488 }
481 489
482 // Remove menu when click outside 490 /** Event Handler when clicking outside of Context Manu */
483 const actionOutsideMenu = e => { 491 const actionOutsideMenu = e => {
484 if (menu.style.display === 'none') return 492 if (menu.style.display === 'none') return
485 const keepMenu = e.target.closest('.keep-menu') || e.target.classList.contains('.keep-menu') 493 const keepMenu = e.target.closest('.keep-menu') || e.target.classList.contains('.keep-menu')
@@ -499,6 +507,6 @@ export const generateMaps = (container, { delay, renderCallback } = {}) => {
499 onRemove(htmlHolder, () => 507 onRemove(htmlHolder, () =>
500 document.removeEventListener('click', actionOutsideMenu), 508 document.removeEventListener('click', actionOutsideMenu),
501 ) 509 )
502 // }}} 510
503 return Object.seal(dumbymap) 511 return Object.seal(dumbymap)
504} 512}