aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/Layout.mjs57
-rw-r--r--src/MenuItem.mjs77
-rw-r--r--src/dumbyUtils.mjs28
-rw-r--r--src/dumbymap.mjs19
-rw-r--r--src/editor.mjs83
-rw-r--r--src/utils.mjs5
6 files changed, 255 insertions, 14 deletions
diff --git a/src/Layout.mjs b/src/Layout.mjs
index 3c4ea3d..6bb6282 100644
--- a/src/Layout.mjs
+++ b/src/Layout.mjs
@@ -1,7 +1,15 @@
1import PlainDraggable from 'plain-draggable' 1import PlainDraggable from 'plain-draggable'
2import { onRemove, animateRectTransition } from './utils' 2import { onRemove, animateRectTransition } from './utils'
3 3
4/**
5 * Layout. Basic class for layout
6 */
4export class Layout { 7export class Layout {
8 /**
9 * constructor.
10 *
11 * @param {} options
12 */
5 constructor (options = {}) { 13 constructor (options = {}) {
6 if (!options.name) throw Error('Layout name is not given') 14 if (!options.name) throw Error('Layout name is not given')
7 this.name = options.name 15 this.name = options.name
@@ -9,12 +17,28 @@ export class Layout {
9 this.leaveHandler = options.leaveHandler 17 this.leaveHandler = options.leaveHandler
10 } 18 }
11 19
20 /**
21 * valueOf.
22 */
12 valueOf = () => this.name 23 valueOf = () => this.name
13} 24}
14 25
26/**
27 * Side-By-Side Layout, HTML content and Showcase show on left/right side
28 *
29 * @extends {Layout}
30 */
15export class SideBySide extends Layout { 31export class SideBySide extends Layout {
32 /**
33 * @type {}
34 */
16 name = 'side-by-side' 35 name = 'side-by-side'
17 36
37 /**
38 * enterHandler.
39 *
40 * @param {}
41 */
18 enterHandler = ({ container, htmlHolder, showcase }) => { 42 enterHandler = ({ container, htmlHolder, showcase }) => {
19 const bar = document.createElement('div') 43 const bar = document.createElement('div')
20 bar.className = 'bar' 44 bar.className = 'bar'
@@ -46,20 +70,43 @@ export class SideBySide extends Layout {
46 onRemove(bar, () => draggable.remove()) 70 onRemove(bar, () => draggable.remove())
47 } 71 }
48 72
73 /**
74 * leaveHandler.
75 *
76 * @param {}
77 */
49 leaveHandler = ({ container }) => { 78 leaveHandler = ({ container }) => {
50 container.querySelector('.bar')?.remove() 79 container.querySelector('.bar')?.remove()
51 } 80 }
52} 81}
53 82
83/**
84 * Overlay Layout, Showcase occupies viewport, and HTML content becomes draggable blocks
85 *
86 * @extends {Layout}
87 */
54export class Overlay extends Layout { 88export class Overlay extends Layout {
89 /**
90 * @type {}
91 */
55 name = 'overlay' 92 name = 'overlay'
56 93
94 /**
95 * saveLeftTopAsData.
96 *
97 * @param {} element
98 */
57 saveLeftTopAsData = element => { 99 saveLeftTopAsData = element => {
58 const { left, top } = element.getBoundingClientRect() 100 const { left, top } = element.getBoundingClientRect()
59 element.setAttribute('data-left', left) 101 element.setAttribute('data-left', left)
60 element.setAttribute('data-top', top) 102 element.setAttribute('data-top', top)
61 } 103 }
62 104
105 /**
106 * addDraggable.
107 *
108 * @param {} element
109 */
63 addDraggable = element => { 110 addDraggable = element => {
64 // Make sure current element always on top 111 // Make sure current element always on top
65 const siblings = Array.from( 112 const siblings = Array.from(
@@ -119,6 +166,11 @@ export class Overlay extends Layout {
119 }) 166 })
120 } 167 }
121 168
169 /**
170 * enterHandler.
171 *
172 * @param {}
173 */
122 enterHandler = ({ htmlHolder, blocks }) => { 174 enterHandler = ({ htmlHolder, blocks }) => {
123 // FIXME It is weird rect from this method and this scope are different... 175 // FIXME It is weird rect from this method and this scope are different...
124 blocks.forEach(this.saveLeftTopAsData) 176 blocks.forEach(this.saveLeftTopAsData)
@@ -197,6 +249,11 @@ export class Overlay extends Layout {
197 }) 249 })
198 } 250 }
199 251
252 /**
253 * leaveHandler.
254 *
255 * @param {}
256 */
200 leaveHandler = ({ htmlHolder, blocks }) => { 257 leaveHandler = ({ htmlHolder, blocks }) => {
201 const resumeFromDraggable = block => { 258 const resumeFromDraggable = block => {
202 const draggableContainer = block.closest('.draggable-block') 259 const draggableContainer = block.closest('.draggable-block')
diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs
index fe0bd99..864bc05 100644
--- a/src/MenuItem.mjs
+++ b/src/MenuItem.mjs
@@ -1,6 +1,16 @@
1import { shiftByWindow } from './utils.mjs' 1import { shiftByWindow } from './utils.mjs'
2 2
3/**
4 * Item. Basic Element for menu item
5 *
6 * @extends {window.HTMLDivElement}
7 */
3export class Item extends window.HTMLDivElement { 8export class Item extends window.HTMLDivElement {
9 /**
10 * constructor.
11 *
12 * @param {}
13 */
4 constructor ({ text, innerHTML, onclick, style, className, onmouseover }) { 14 constructor ({ text, innerHTML, onclick, style, className, onmouseover }) {
5 super() 15 super()
6 this.innerHTML = innerHTML ?? text 16 this.innerHTML = innerHTML ?? text
@@ -18,7 +28,17 @@ export class Item extends window.HTMLDivElement {
18} 28}
19window.customElements.define('menu-item', Item, { extends: 'div' }) 29window.customElements.define('menu-item', Item, { extends: 'div' })
20 30
31/**
32 * Folder. Basic Element for menu item, it generate submenu on hover
33 *
34 * @extends {window.HTMLDivElement}
35 */
21export class Folder extends window.HTMLDivElement { 36export class Folder extends window.HTMLDivElement {
37 /**
38 * constructor.
39 *
40 * @param {}
41 */
22 constructor ({ text, innerHTML, items }) { 42 constructor ({ text, innerHTML, items }) {
23 super() 43 super()
24 this.innerHTML = innerHTML ?? text 44 this.innerHTML = innerHTML ?? text
@@ -44,6 +64,11 @@ export class Folder extends window.HTMLDivElement {
44} 64}
45window.customElements.define('menu-folder', Folder, { extends: 'div' }) 65window.customElements.define('menu-folder', Folder, { extends: 'div' })
46 66
67/**
68 * pickMapItem.
69 *
70 * @param {Function[]} options.utils
71 */
47export const pickMapItem = ({ utils }) => 72export const pickMapItem = ({ utils }) =>
48 new Folder({ 73 new Folder({
49 innerHTML: '<span>Maps<span><span class="info">(Tab)</span>', 74 innerHTML: '<span>Maps<span><span class="info">(Tab)</span>',
@@ -59,6 +84,12 @@ export const pickMapItem = ({ utils }) =>
59 ) 84 )
60 }) 85 })
61 86
87/**
88 * pickBlockItem.
89 *
90 * @param {HTMLElement[]} options.blocks
91 * @param {Function[]} options.utils
92 */
62export const pickBlockItem = ({ blocks, utils }) => 93export const pickBlockItem = ({ blocks, utils }) =>
63 new Folder({ 94 new Folder({
64 innerHTML: '<span>Blocks<span><span class="info">(n/p)</span>', 95 innerHTML: '<span>Blocks<span><span class="info">(n/p)</span>',
@@ -92,6 +123,12 @@ export const pickBlockItem = ({ blocks, utils }) =>
92 ) 123 )
93 }) 124 })
94 125
126/**
127 * pickLayoutItem.
128 *
129 * @param {HTEMElement} options.container
130 * @param {String[]} options.layouts
131 */
95export const pickLayoutItem = ({ container, layouts }) => 132export const pickLayoutItem = ({ container, layouts }) =>
96 new Folder({ 133 new Folder({
97 innerHTML: '<span>Layouts<span><span class="info">(x)</span>', 134 innerHTML: '<span>Layouts<span><span class="info">(x)</span>',
@@ -115,6 +152,12 @@ export const pickLayoutItem = ({ container, layouts }) =>
115 ] 152 ]
116 }) 153 })
117 154
155/**
156 * addGeoLink.
157 *
158 * @param {Function[]} options.utils
159 * @param {Range} range
160 */
118export const addGeoLink = ({ utils }, range) => 161export const addGeoLink = ({ utils }, range) =>
119 new Item({ 162 new Item({
120 text: 'Add GeoLink', 163 text: 'Add GeoLink',
@@ -138,7 +181,17 @@ export const addGeoLink = ({ utils }, range) =>
138 } 181 }
139 }) 182 })
140 183
184/**
185 * Suggestion. Menu Item for editor suggestion
186 *
187 * @extends {Item}
188 */
141export class Suggestion extends Item { 189export class Suggestion extends Item {
190 /**
191 * constructor.
192 *
193 * @param {}
194 */
142 constructor ({ text, replace, cm }) { 195 constructor ({ text, replace, cm }) {
143 super({ text }) 196 super({ text })
144 this.replace = replace 197 this.replace = replace
@@ -165,6 +218,13 @@ export class Suggestion extends Item {
165} 218}
166window.customElements.define('menu-item-suggestion', Suggestion, { extends: 'div' }) 219window.customElements.define('menu-item-suggestion', Suggestion, { extends: 'div' })
167 220
221/**
222 * renderResults. return a menu item for reporting render results
223 *
224 * @param {Object} options.modal -- Ojbect of plain-modal
225 * @param {HTMLElement} options.modalContent
226 * @param {HTMLElement} map -- Rendered map element
227 */
168export const renderResults = ({ modal, modalContent }, map) => 228export const renderResults = ({ modal, modalContent }, map) =>
169 new Item({ 229 new Item({
170 text: 'Render Results', 230 text: 'Render Results',
@@ -215,6 +275,13 @@ export const renderResults = ({ modal, modalContent }, map) =>
215 } 275 }
216 }) 276 })
217 277
278/**
279 * printObject. Generate <details> in parent element based on Ojbect properties
280 *
281 * @param {Object} obj
282 * @param {HTMLElement} parentElement
283 * @param {String} name
284 */
218function printObject (obj, parentElement, name = null) { 285function printObject (obj, parentElement, name = null) {
219 // Create <details> and <summary> inside 286 // Create <details> and <summary> inside
220 const detailsEle = document.createElement('details') 287 const detailsEle = document.createElement('details')
@@ -255,12 +322,22 @@ function printObject (obj, parentElement, name = null) {
255 } 322 }
256} 323}
257 324
325/**
326 * toggleBlockFocus. Menu Item for toggling focus on a block
327 *
328 * @param {HTMLElement} block
329 */
258export const toggleBlockFocus = block => 330export const toggleBlockFocus = block =>
259 new Item({ 331 new Item({
260 text: 'Toggle Focus', 332 text: 'Toggle Focus',
261 onclick: () => block.classList.toggle('focus') 333 onclick: () => block.classList.toggle('focus')
262 }) 334 })
263 335
336/**
337 * toggleMapFocus. Menu Item for toggling focus on a map
338 *
339 * @param {HTMLElement} map
340 */
264export const toggleMapFocus = map => 341export const toggleMapFocus = map =>
265 new Item({ 342 new Item({
266 text: 'Toggle Focus', 343 text: 'Toggle Focus',
diff --git a/src/dumbyUtils.mjs b/src/dumbyUtils.mjs
index b0845bd..5182a8f 100644
--- a/src/dumbyUtils.mjs
+++ b/src/dumbyUtils.mjs
@@ -1,5 +1,10 @@
1import LeaderLine from 'leader-line' 1import LeaderLine from 'leader-line'
2 2
3/**
4 * focusNextMap.
5 *
6 * @param {Boolean} reverse -- focus previous map
7 */
3export function focusNextMap (reverse = false) { 8export function focusNextMap (reverse = false) {
4 const renderedList = this.utils.renderedMaps() 9 const renderedList = this.utils.renderedMaps()
5 const index = renderedList.findIndex(e => e.classList.contains('focus')) 10 const index = renderedList.findIndex(e => e.classList.contains('focus'))
@@ -10,6 +15,11 @@ export function focusNextMap (reverse = false) {
10 nextMap.scrollIntoView({ behavior: 'smooth' }) 15 nextMap.scrollIntoView({ behavior: 'smooth' })
11} 16}
12 17
18/**
19 * focusNextBlock.
20 *
21 * @param {Boolean} reverse -- focus previous block
22 */
13export function focusNextBlock (reverse = false) { 23export function focusNextBlock (reverse = false) {
14 const blocks = this.blocks.filter(b => 24 const blocks = this.blocks.filter(b =>
15 b.checkVisibility({ 25 b.checkVisibility({
@@ -27,7 +37,12 @@ export function focusNextBlock (reverse = false) {
27 scrollToBlock(nextBlock) 37 scrollToBlock(nextBlock)
28} 38}
29 39
30// Consider block is bigger then viewport height 40/**
41 * scrollToBlock. Smoothly scroll to target block.
42 * If block is bigger than viewport, then pick strategy wisely.
43 *
44 * @param {HTMLElement} block -- Scroll to this element
45 */
31export const scrollToBlock = block => { 46export const scrollToBlock = block => {
32 const parentRect = block.parentElement.getBoundingClientRect() 47 const parentRect = block.parentElement.getBoundingClientRect()
33 const scrollBlock = 48 const scrollBlock =
@@ -37,10 +52,18 @@ export const scrollToBlock = block => {
37 block.scrollIntoView({ behavior: 'smooth', block: scrollBlock }) 52 block.scrollIntoView({ behavior: 'smooth', block: scrollBlock })
38} 53}
39 54
55/**
56 * focusDelay. Delay of throttle, value changes by cases
57 */
40export function focusDelay () { 58export function focusDelay () {
41 return window.window.getComputedStyle(this.showcase).display === 'none' ? 50 : 300 59 return window.window.getComputedStyle(this.showcase).display === 'none' ? 50 : 300
42} 60}
43 61
62/**
63 * switchToNextLayout.
64 *
65 * @param {Boolean} reverse -- Switch to previous one
66 */
44export function switchToNextLayout (reverse = false) { 67export function switchToNextLayout (reverse = false) {
45 const layouts = this.layouts 68 const layouts = this.layouts
46 const currentLayoutName = this.container.getAttribute('data-layout') 69 const currentLayoutName = this.container.getAttribute('data-layout')
@@ -54,6 +77,9 @@ export function switchToNextLayout (reverse = false) {
54 this.container.setAttribute('data-layout', nextLayout.name) 77 this.container.setAttribute('data-layout', nextLayout.name)
55} 78}
56 79
80/**
81 * removeBlockFocus.
82 */
57export function removeBlockFocus () { 83export function removeBlockFocus () {
58 this.blocks.forEach(b => b.classList.remove('focus')) 84 this.blocks.forEach(b => b.classList.remove('focus'))
59} 85}
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs
index 0c6f0be..744d216 100644
--- a/src/dumbymap.mjs
+++ b/src/dumbymap.mjs
@@ -21,6 +21,12 @@ const layouts = [
21] 21]
22const mapCache = {} 22const mapCache = {}
23 23
24/**
25 * markdown2HTML.
26 *
27 * @param {HTMLElement} container -- Target Element to include generated HTML contents
28 * @param {String} mdContent -- Texts in Markdown
29 */
24export const markdown2HTML = (container, mdContent) => { 30export const markdown2HTML = (container, mdContent) => {
25 // Render: Markdown -> HTML {{{ 31 // Render: Markdown -> HTML {{{
26 container.replaceChildren() 32 container.replaceChildren()
@@ -83,7 +89,7 @@ export const markdown2HTML = (container, mdContent) => {
83 state.tokens.push(new state.Token('dumby_block_close', '', -1)) 89 state.tokens.push(new state.Token('dumby_block_close', '', -1))
84 }) 90 })
85 91
86 const contentWithToc = '${toc}\n\n\n' + mdContent // eslint-disable-line 92 const contentWithToc = '${toc}\n\n\n' + mdContent
87 htmlHolder.innerHTML = md.render(contentWithToc) 93 htmlHolder.innerHTML = md.render(contentWithToc)
88 94
89 // TODO Do this in markdown-it 95 // TODO Do this in markdown-it
@@ -96,6 +102,13 @@ export const markdown2HTML = (container, mdContent) => {
96 return container 102 return container
97 // }}} 103 // }}}
98} 104}
105
106/**
107 * generateMaps.
108 *
109 * @param {HTMLElement} container -- Target Element contains HTML contents
110 * @param {Object} dumbymap -- Include and Elements and Methods about managing contents
111 */
99export const generateMaps = (container, { delay, mapCallback }) => { 112export const generateMaps = (container, { delay, mapCallback }) => {
100 container.classList.add('Dumby') 113 container.classList.add('Dumby')
101 container.removeAttribute('data-layout') 114 container.removeAttribute('data-layout')
@@ -159,7 +172,7 @@ export const generateMaps = (container, { delay, mapCallback }) => {
159 const isAnchorPointedBy = link => anchor => { 172 const isAnchorPointedBy = link => anchor => {
160 const mapContainer = anchor.closest('.mapclay') 173 const mapContainer = anchor.closest('.mapclay')
161 const isTarget = !link.targets || link.targets.includes(mapContainer.id) 174 const isTarget = !link.targets || link.targets.includes(mapContainer.id)
162 return anchor.title === link.url.pathname && isTarget 175 return anchor.title === link.url.searchParams.get('text') && isTarget
163 } 176 }
164 177
165 const isAnchorVisible = anchor => { 178 const isAnchorVisible = anchor => {
@@ -366,7 +379,7 @@ export const generateMaps = (container, { delay, mapCallback }) => {
366 mapCallback?.call(this, mapElement) 379 mapCallback?.call(this, mapElement)
367 const markers = geoLinks 380 const markers = geoLinks
368 .filter(link => !link.targets || link.targets.includes(mapElement.id)) 381 .filter(link => !link.targets || link.targets.includes(mapElement.id))
369 .map(link => ({ xy: link.xy, title: link.url.pathname })) 382 .map(link => ({ xy: link.xy, title: link.url.searchParams.get('text') }))
370 383
371 // FIXME Here may cause error 384 // FIXME Here may cause error
372 // Add markers with Geolinks 385 // Add markers with Geolinks
diff --git a/src/editor.mjs b/src/editor.mjs
index 36f0fdc..e9ee84a 100644
--- a/src/editor.mjs
+++ b/src/editor.mjs
@@ -23,6 +23,9 @@ new window.MutationObserver(() => {
23 attributeFilter: ['data-mode'], 23 attributeFilter: ['data-mode'],
24 attributeOldValue: true 24 attributeOldValue: true
25}) 25})
26/**
27 * toggle editing mode
28 */
26const toggleEditing = () => { 29const toggleEditing = () => {
27 const mode = context.getAttribute('data-mode') 30 const mode = context.getAttribute('data-mode')
28 context.setAttribute('data-mode', mode === 'editing' ? '' : 'editing') 31 context.setAttribute('data-mode', mode === 'editing' ? '' : 'editing')
@@ -128,6 +131,11 @@ const editor = new EasyMDE({
128 131
129const cm = editor.codemirror 132const cm = editor.codemirror
130 133
134/**
135 * get state of website from hash string
136 *
137 * @param {String} hash
138 */
131const getStateFromHash = hash => { 139const getStateFromHash = hash => {
132 const hashValue = hash.substring(1) 140 const hashValue = hash.substring(1)
133 const stateString = decodeURIComponent(hashValue) 141 const stateString = decodeURIComponent(hashValue)
@@ -138,6 +146,11 @@ const getStateFromHash = hash => {
138 } 146 }
139} 147}
140 148
149/**
150 * get editor content from hash string
151 *
152 * @param {} hash
153 */
141const getContentFromHash = hash => { 154const getContentFromHash = hash => {
142 const state = getStateFromHash(hash) 155 const state = getStateFromHash(hash)
143 return state.content 156 return state.content
@@ -154,7 +167,13 @@ if (contentFromHash) {
154} 167}
155// }}} 168// }}}
156// Set up logic about editor content {{{ 169// Set up logic about editor content {{{
157const afterMapRendered = _ => { 170/**
171 * afterMapRendered. Callback of map rendered
172 *
173 * @param {HTEMLElement} map
174 */
175const afterMapRendered = map => {
176 console.info(map)
158 // mapHolder.oncontextmenu = (event) => { 177 // mapHolder.oncontextmenu = (event) => {
159 // event.preventDefault() 178 // event.preventDefault()
160 // const lonLat = mapHolder.renderer.unproject([event.x, event.y]) 179 // const lonLat = mapHolder.renderer.unproject([event.x, event.y])
@@ -164,7 +183,9 @@ const afterMapRendered = _ => {
164markdown2HTML(HtmlContainer, editor.value()) 183markdown2HTML(HtmlContainer, editor.value())
165dumbymap = generateMaps(HtmlContainer, afterMapRendered) 184dumbymap = generateMaps(HtmlContainer, afterMapRendered)
166 185
167// Quick hack to style lines inside code block 186/**
187 * addClassToCodeLines. Quick hack to style lines inside code block
188 */
168const addClassToCodeLines = () => { 189const addClassToCodeLines = () => {
169 const lines = cm.getLineHandle(0).parent.lines 190 const lines = cm.getLineHandle(0).parent.lines
170 let insideCodeBlock = false 191 let insideCodeBlock = false
@@ -180,6 +201,11 @@ const addClassToCodeLines = () => {
180} 201}
181addClassToCodeLines() 202addClassToCodeLines()
182 203
204/**
205 * completeForCodeBlock.
206 *
207 * @param {Object} change -- codemirror change object
208 */
183const completeForCodeBlock = change => { 209const completeForCodeBlock = change => {
184 const line = change.to.line 210 const line = change.to.line
185 if (change.origin === '+input') { 211 if (change.origin === '+input') {
@@ -234,6 +260,9 @@ const completeForCodeBlock = change => {
234// } 260// }
235// })() 261// })()
236 262
263/**
264 * update content of HTML about Dumbymap
265 */
237const updateDumbyMap = () => { 266const updateDumbyMap = () => {
238 markdown2HTML(HtmlContainer, editor.value()) 267 markdown2HTML(HtmlContainer, editor.value())
239 // TODO Test if generate maps intantly is OK with map cache 268 // TODO Test if generate maps intantly is OK with map cache
@@ -309,7 +338,11 @@ fetch(defaultApply)
309 }) 338 })
310 .catch(err => console.warn(`Fail to get aliases from ${defaultApply}`, err)) 339 .catch(err => console.warn(`Fail to get aliases from ${defaultApply}`, err))
311// }}} 340// }}}
312// FUNCTION: Check if current token is inside code block {{{ 341/**
342 * insideCodeblockForMap. Check if current token is inside code block {{{
343 *
344 * @param {} anchor
345 */
313const insideCodeblockForMap = anchor => { 346const insideCodeblockForMap = anchor => {
314 const token = cm.getTokenAt(anchor) 347 const token = cm.getTokenAt(anchor)
315 const insideCodeBlock = 348 const insideCodeBlock =
@@ -330,7 +363,11 @@ const insideCodeblockForMap = anchor => {
330 return false 363 return false
331} 364}
332// }}} 365// }}}
333// FUNCTION: Get Renderer by cursor position in code block {{{ 366/**
367 * getLineWithRenderer. Get Renderer by cursor position in code block {{{
368 *
369 * @param {Object} anchor -- Codemirror Anchor Object
370 */
334const getLineWithRenderer = anchor => { 371const getLineWithRenderer = anchor => {
335 const currentLine = anchor.line 372 const currentLine = anchor.line
336 if (!cm.getLine) return null 373 if (!cm.getLine) return null
@@ -365,7 +402,12 @@ const getLineWithRenderer = anchor => {
365 return null 402 return null
366} 403}
367// }}} 404// }}}
368// FUNCTION: Return suggestions for valid options {{{ 405/**
406 * getSuggestionsForOptions. Return suggestions for valid options {{{
407 *
408 * @param {Boolean} optionTyped
409 * @param {Object[]} validOptions
410 */
369const getSuggestionsForOptions = (optionTyped, validOptions) => { 411const getSuggestionsForOptions = (optionTyped, validOptions) => {
370 let suggestOptions = [] 412 let suggestOptions = []
371 413
@@ -389,7 +431,11 @@ const getSuggestionsForOptions = (optionTyped, validOptions) => {
389 ) 431 )
390} 432}
391// }}} 433// }}}
392// FUNCTION: Return suggestion for example of option value {{{ 434/**
435 * getSuggestionFromMapOption. Return suggestion for example of option value {{{
436 *
437 * @param {Object} option
438 */
393const getSuggestionFromMapOption = option => { 439const getSuggestionFromMapOption = option => {
394 if (!option.example) return null 440 if (!option.example) return null
395 441
@@ -404,7 +450,11 @@ const getSuggestionFromMapOption = option => {
404 }) 450 })
405} 451}
406// }}} 452// }}}
407// FUNCTION: Return suggestions from aliases {{{ 453/**
454 * getSuggestionsFromAliases. Return suggestions from aliases {{{
455 *
456 * @param {Object} option
457 */
408const getSuggestionsFromAliases = option => 458const getSuggestionsFromAliases = option =>
409 Object.entries(aliasesForMapOptions[option.valueOf()] ?? {})?.map(record => { 459 Object.entries(aliasesForMapOptions[option.valueOf()] ?? {})?.map(record => {
410 const [alias, value] = record 460 const [alias, value] = record
@@ -416,7 +466,11 @@ const getSuggestionsFromAliases = option =>
416 }) 466 })
417 }) ?? [] 467 }) ?? []
418// }}} 468// }}}
419// FUCNTION: Handler for map codeblock {{{ 469/**
470 * handleTypingInCodeBlock. Handler for map codeblock {{{
471 *
472 * @param {Object} anchor -- Codemirror Anchor Object
473 */
420const handleTypingInCodeBlock = anchor => { 474const handleTypingInCodeBlock = anchor => {
421 const text = cm.getLine(anchor.line) 475 const text = cm.getLine(anchor.line)
422 if (text.match(/^\s\+$/) && text.length % 2 !== 0) { 476 if (text.match(/^\s\+$/) && text.length % 2 !== 0) {
@@ -429,7 +483,11 @@ const handleTypingInCodeBlock = anchor => {
429 } 483 }
430} 484}
431// }}} 485// }}}
432// FUNCTION: get suggestions by current input {{{ 486/**
487 * getSuggestions. Get suggestions by current input {{{
488 *
489 * @param {Object} anchor -- Codemirror Anchor Object
490 */
433const getSuggestions = anchor => { 491const getSuggestions = anchor => {
434 const text = cm.getLine(anchor.line) 492 const text = cm.getLine(anchor.line)
435 493
@@ -543,7 +601,12 @@ const getSuggestions = anchor => {
543 return [] 601 return []
544} 602}
545// }}} 603// }}}
546// {{{ FUNCTION: Show element about suggestions 604/**
605 * addSuggestions. Show element about suggestions {{{
606 *
607 * @param {Object} anchor -- Codemirror Anchor Object
608 * @param {Suggestion[]} suggestions
609 */
547const addSuggestions = (anchor, suggestions) => { 610const addSuggestions = (anchor, suggestions) => {
548 if (suggestions.length === 0) { 611 if (suggestions.length === 0) {
549 menu.style.display = 'none' 612 menu.style.display = 'none'
diff --git a/src/utils.mjs b/src/utils.mjs
index c9a2457..ffd8978 100644
--- a/src/utils.mjs
+++ b/src/utils.mjs
@@ -88,6 +88,11 @@ export function throttle (func, delay) {
88 } 88 }
89} 89}
90 90
91/**
92 * shiftByWindow. make sure HTMLElement inside viewport
93 *
94 * @param {HTMLElement} element
95 */
91export const shiftByWindow = element => { 96export const shiftByWindow = element => {
92 const rect = element.getBoundingClientRect() 97 const rect = element.getBoundingClientRect()
93 const offsetX = window.innerWidth - rect.left - rect.width 98 const offsetX = window.innerWidth - rect.left - rect.width