From 1caf56dc0a2bbf4bb484fe4f312b5229a63aace3 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Wed, 16 Oct 2024 16:57:47 +0800 Subject: feat: add simple script to test mapclay * add more options for generateMaps for general purposes * add rollup config for adding script into addon --- addon/index.mjs | 17 +++++++ addon/manifest.json | 10 +++- scripts/rollup.config.js | 55 ++++++++++++++++++-- src/dumbymap.mjs | 128 +++++++++++++++++++++++++++++------------------ 4 files changed, 153 insertions(+), 57 deletions(-) create mode 100644 addon/index.mjs diff --git a/addon/index.mjs b/addon/index.mjs new file mode 100644 index 0000000..323edf1 --- /dev/null +++ b/addon/index.mjs @@ -0,0 +1,17 @@ +const { Leaflet } = window.mapclay.renderers +const simpleRender = window.mapclay.renderWith(config => ({ + use: 'Leaflet', + width: '100%', + height: '200px', + XYZ: 'https://tile.openstreetmap.jp/styles/osm-bright/512/{z}/{x}/{y}.png', + ...config, + aliases: { + use: { Leaflet }, + ...(config.aliases ?? {}), + }, +})) + +window.generateMaps(document.querySelector('main') ?? document.body, { + initialLayout: '', + render: simpleRender, +}) diff --git a/addon/manifest.json b/addon/manifest.json index 27433b3..9cc6607 100644 --- a/addon/manifest.json +++ b/addon/manifest.json @@ -11,8 +11,14 @@ "content_scripts": [ { - "matches": ["*://*.mozilla.org/*"], - "js": ["index.mjs"], + "matches": [ + "*://*.mozilla.org/*", + "*://hackmd.io/*" + ], + "js": [ + "dumbymap.mjs", + "index.mjs" + ], "css": [ "css/dumbymap.css" ] diff --git a/scripts/rollup.config.js b/scripts/rollup.config.js index d4af05f..7dc9f75 100644 --- a/scripts/rollup.config.js +++ b/scripts/rollup.config.js @@ -5,7 +5,25 @@ import { existsSync } from 'fs' import { join } from 'path' import { bundleStats } from 'rollup-plugin-bundle-stats' -const production = !process.env.ROLLUP_WATCH +const prod = process.env.PRODUCTION +const addon = process.env.ADDON + +function resolve (file, origin) { + // Your way to resolve local include path +} + +function pathResolve (options) { + return { + resolveId: function (file, origin) { + // Your local include path must either starts with `./` or `../` + if (file.startsWith('./') || file.startsWith('../')) { + // Return an absolute include path + return resolve(file, origin) + } + return null // Continue to the next plugins! + }, + } +} const general = { output: [ @@ -13,7 +31,6 @@ const general = { dir: './dist', format: 'esm', entryFileNames: '[name].mjs', - sourcemap: 'true', }, ], watch: { @@ -42,12 +59,13 @@ const general = { return null }, }, + pathResolve(), node(), commonjs(), - production && terser({ + prod && terser({ keep_fnames: true, }), - production && bundleStats(), + prod && bundleStats(), ], } @@ -60,4 +78,31 @@ export default [ }, ] .map(config => ({ ...general, ...config })) - .filter((config) => production || config.input.match(/editor/)) + .filter(config => { + if (addon) return config.input.match(/dumbymap/) + if (!prod) return config.input.match(/editor/) + }) + .map(config => { + if (!addon) return config + + config.output.forEach(o => o.dir = './addon') + config.plugins.push({ + name: 'remove-exports', + transform (code, id) { + if (id.includes(config.input)) { + // remove export keyword for addon + const transformedCode = code.replace(/\n(\s*)export\s*/g, '$1') + return { + code: [ + transformedCode, + 'window.generateMaps = generateMaps', + 'window.mapclay = mapclay', + ].join('\n'), + } + } + return null + }, + }) + + return config + }) diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 8e26ee6..ee61838 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs @@ -3,7 +3,7 @@ import MarkdownItAnchor from 'markdown-it-anchor' import MarkdownItFootnote from 'markdown-it-footnote' import MarkdownItFrontMatter from 'markdown-it-front-matter' import MarkdownItInjectLinenumbers from 'markdown-it-inject-linenumbers' -import { renderWith, defaultAliases, parseConfigsFromYaml } from 'mapclay' +import * as mapclay from 'mapclay' import { replaceTextNodes, onRemove, animateRectTransition, throttle, shiftByWindow } from './utils' import { Layout, SideBySide, Overlay } from './Layout' import * as utils from './dumbyUtils' @@ -85,6 +85,68 @@ export const markdown2HTML = (container, mdContent) => { return container } +/** + * defaultBlocks. + * @description Default way to get blocks from Semantic HTML + * @param {HTMLElement} root + */ +const defaultBlocks = root => { + const articles = root.querySelectorAll('article') + if (articles.length > 2) return articles + + const others = Array.from( + root.querySelectorAll(':has(>p, >blockquote, >pre, >ul, >ol, >table, >details)'), + ) + .map(e => { + e.classList.add('dumby-block') + return e + }) + .filter(e => { + const isContained = e.parentElement.closest('.dumby-block') + if (isContained) e.classList.remove('dumby-block') + return !isContained + }) + + return others +} + +/** + * updateAttributeByStep. + * @description Update data attribute by steps of map render + * @param {Object} - renderer which is running steps + */ +const updateAttributeByStep = ({ results, target, steps }) => { + let passNum = results.filter( + r => r.type === 'render' && r.state.match(/success|skip/), + ).length + const total = steps.length + passNum += `/${total}` + + const final = results.filter(r => r.type === 'render').length === total + + // FIXME HACK use MutationObserver for animation + if (!target.animations) target.animations = Promise.resolve() + target.animations = target.animations.then(async () => { + await new Promise(resolve => setTimeout(resolve, 100)) + if (final) passNum += '\x20' + target.dataset.report = passNum + + if (final) setTimeout(() => delete target.dataset.report, 100) + }) +} + +/** Get default render method by converter */ +const defaultRender = mapclay.renderWith(config => ({ + use: config.use ?? 'Leaflet', + width: '100%', + ...config, + aliases: { + ...mapclay.defaultAliases, + ...(config.aliases ?? {}), + }, + stepCallback: updateAttributeByStep, +})) + /** * Generates maps based on the provided configuration * @@ -96,16 +158,19 @@ export const markdown2HTML = (container, mdContent) => { */ export const generateMaps = (container, { crs = 'EPSG:4326', + initialLayout, layouts = [], delay, renderCallback, - addBlocks = htmlHolder => Array.from(htmlHolder.querySelectorAll('article')), + addBlocks = defaultBlocks, + render = defaultRender, } = {}) => { - /** Prepare Contaner/HTML-Holder/Showcase */ + /** Prepare Contaner */ container.classList.add('Dumby') delete container.dataset.layout - container.dataset.layout = defaultLayouts[0].name + container.dataset.layout = initialLayout ?? defaultLayouts[0].name + /** Prepare Semantic HTML part and blocks of contents inside */ const htmlHolder = container.querySelector('.SemanticHtml, :has(article, section)') ?? container.firstElementChild htmlHolder.classList.add('.SemanticHtml') const blocks = addBlocks(htmlHolder) @@ -114,12 +179,13 @@ export const generateMaps = (container, { b.dataset.total = blocks.length }) + /** Prepare Showcase */ const showcase = document.createElement('div') container.appendChild(showcase) showcase.classList.add('Showcase') - const renderPromises = [] - /** Prepare Modal */ + /** Prepare Other Variables */ + const renderPromises = [] const modalContent = document.createElement('div') container.appendChild(modalContent) const modal = new PlainModal(modalContent) @@ -392,63 +458,25 @@ export const generateMaps = (container, { const elementsWithMapConfig = Array.from( container.querySelectorAll(mapBlockSelector) ?? [], ) - /** - * updateAttributeByStep. - * - * @param {Object} - renderer which is running steps - */ - const updateAttributeByStep = ({ results, target, steps }) => { - let passNum = results.filter( - r => r.type === 'render' && r.state.match(/success|skip/), - ).length - const total = steps.length - passNum += `/${total}` - - const final = results.filter(r => r.type === 'render').length === total - - // FIXME HACK use MutationObserver for animation - if (!target.animations) target.animations = Promise.resolve() - target.animations = target.animations.then(async () => { - await new Promise(resolve => setTimeout(resolve, 100)) - if (final) passNum += '\x20' - target.dataset.report = passNum - - if (final) setTimeout(() => delete target.dataset.report, 100) - }) + if (elementsWithMapConfig.length === 0) { + const map = document.createElement('pre') + map.textContent = '#Created by DumbyMap' + htmlHolder.insertBefore(map, htmlHolder.firstElementChild) + elementsWithMapConfig.push(map) } - /** - * config converter for mapclay.renderWith() - * - * @param {Object} config - * @return {Object} - converted config - */ - const configConverter = config => ({ - use: config.use ?? 'Leaflet', - width: '100%', - ...config, - aliases: { - ...defaultAliases, - ...(config.aliases ?? {}), - }, - stepCallback: updateAttributeByStep, - }) - - /** Get render method by converter */ - const render = renderWith(configConverter) /** Render each taget element for maps */ let order = 0 elementsWithMapConfig.forEach(target => { // Get text in code block starts with markdown text '```map' const configText = target - .querySelector('.language-map') .textContent // BE CAREFUL!!! 0xa0 char is "non-breaking spaces" in HTML text content // replace it by normal space .replace(/\u00A0/g, '\u0020') let configList = [] try { - configList = parseConfigsFromYaml(configText).map(assignMapId) + configList = mapclay.parseConfigsFromYaml(configText).map(assignMapId) } catch (_) { console.warn('Fail to parse yaml config for element', target) return -- cgit v1.2.3-70-g09d2 From a6f5b8634cd0681cea9468e4ee725b5b125ddfe7 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Wed, 16 Oct 2024 16:58:12 +0800 Subject: feat(CSS): dont't modify origin CSS unless layout is specified --- src/css/dumbymap.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/css/dumbymap.css b/src/css/dumbymap.css index dc1f59b..fdf3bdd 100644 --- a/src/css/dumbymap.css +++ b/src/css/dumbymap.css @@ -166,7 +166,7 @@ root { } } -.dumby-block { +.Dumby:not([data-layout=""]) .dumby-block { padding: 1rem 1rem 1rem 2rem; position: relative; -- cgit v1.2.3-70-g09d2 From 847872c5ed3cdcec572e1cc5cfd43498f828e1cd Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Wed, 16 Oct 2024 16:59:38 +0800 Subject: fix: position of contextmenu --- src/dumbymap.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index ee61838..c03680d 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs @@ -538,7 +538,7 @@ export const generateMaps = (container, { container.oncontextmenu = e => { menu.replaceChildren() menu.style.display = 'block' - menu.style.cssText = `left: ${e.x - menu.offsetParent.offsetLeft + 10}px; top: ${e.y - menu.offsetParent.offsetTop + 5}px;` + menu.style.cssText = `left: ${e.clientX - menu.offsetParent.offsetLeft + 10}px; top: ${e.clientY - menu.offsetParent.offsetTop + 5}px;` e.preventDefault() // Menu Items for map -- cgit v1.2.3-70-g09d2 From eb10e589e735f00e1aa8cccf8843b2d1e7671a42 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Wed, 16 Oct 2024 17:04:21 +0800 Subject: feat: add npm script for addon --- .gitignore | 3 +++ package.json | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3e80267..b42d1dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ dist/ docs/ +addon/**js +addon/**css +!addon/index** doc-coverage/ node_modules/ package-lock.json diff --git a/package.json b/package.json index d6f8b40..392ca85 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "style": "scripts/stylelint.sh", "docs": "jsdoc -c scripts/jsdoc.conf src/; xdg-open http://localhost:8080/docs/", "prepack": "npm run lint && npm run style && npm run build", - "postpack": "rm -rf dist/css dist/renderers; npm run build-resources; ln -sf `pwd`/src/css dist; cp node_modules/easymde/dist/easymde.min.css src/css; ln -sf `pwd`/node_modules/mapclay/dist/renderers dist" + "postpack": "rm -rf dist/css dist/renderers; npm run build-resources; ln -sf `pwd`/src/css dist; cp node_modules/easymde/dist/easymde.min.css src/css; ln -sf `pwd`/node_modules/mapclay/dist/renderers dist", + "addon": "cp src/css/dumbymap.css addon/css; ADDON=true rollup -c scripts/rollup.config.js" }, "devDependencies": { "@rollup/plugin-alias": "^5.1.1", -- cgit v1.2.3-70-g09d2 From d805347e492d571b5ac5f4d310b6e39466ca87a9 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Wed, 16 Oct 2024 18:56:28 +0800 Subject: fix: prevent define web components twice --- src/MenuItem.mjs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs index 7ce75f6..74b01d5 100644 --- a/src/MenuItem.mjs +++ b/src/MenuItem.mjs @@ -40,7 +40,9 @@ export class Item extends window.HTMLDivElement { } } } -window.customElements.define('dumby-menu-item', Item, { extends: 'div' }) +if (!window.customElements.get('dumby-menu-item')) { + window.customElements.define('dumby-menu-item', Item, { extends: 'div' }) +} /** * Basic Element for menu item that generates a submenu on hover @@ -80,7 +82,9 @@ export class Folder extends window.HTMLDivElement { } } } -window.customElements.define('menu-folder', Folder, { extends: 'div' }) +if (!window.customElements.get('menu-folder')) { + window.customElements.define('menu-folder', Folder, { extends: 'div' }) +} /** * Creates a menu item for picking a map @@ -232,7 +236,9 @@ export class Suggestion extends Item { } } } -window.customElements.define('menu-item-suggestion', Suggestion, { extends: 'div' }) +if (!window.customElements.get('menu-item-suggestion')) { + window.customElements.define('menu-item-suggestion', Suggestion, { extends: 'div' }) +} /** * renderResults. return a menu item for reporting render results -- cgit v1.2.3-70-g09d2 From fa4dfcbfa6361417e325f90d59e86ae8d4765807 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Wed, 16 Oct 2024 18:57:01 +0800 Subject: feat(CSS): do not make GeoLink bolder while hovering --- src/css/dumbymap.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/css/dumbymap.css b/src/css/dumbymap.css index fdf3bdd..c0bb1a9 100644 --- a/src/css/dumbymap.css +++ b/src/css/dumbymap.css @@ -161,7 +161,7 @@ root { &:hover, &.drag { background-image: none; - font-weight: bolder; + /* font-weight: bolder; */ text-decoration: none; } } -- cgit v1.2.3-70-g09d2 From 42ae19120e9b9e907e405ad1a272de11e0d37e2d Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Wed, 16 Oct 2024 20:44:42 +0800 Subject: feat: include more domains for addon --- addon/manifest.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addon/manifest.json b/addon/manifest.json index 9cc6607..e97ae50 100644 --- a/addon/manifest.json +++ b/addon/manifest.json @@ -13,7 +13,8 @@ { "matches": [ "*://*.mozilla.org/*", - "*://hackmd.io/*" + "*://hackmd.io/*", + "*://*.ptt.cc/*" ], "js": [ "dumbymap.mjs", -- cgit v1.2.3-70-g09d2 From 6ad14a3daf3292048de1a4c72cabca243d03b103 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Wed, 16 Oct 2024 20:45:41 +0800 Subject: fix: misused for result of match --- src/dumbymap.mjs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index c03680d..55d29d3 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs @@ -242,11 +242,8 @@ export const generateMaps = (container, { fromEPSGCode(crs).then(() => resolve()) }) const addGeoSchemeByText = new Promise(resolve => { - const coordPatterns = [ - /[\x28\x5B\uFF08]\D*(-?\d+\.?\d*)([\x2F\s])(-?\d+\.?\d*)\D*[\x29\x5D\uFF09]/, - /(-?\d+\.?\d*)([,\uFF0C])(-?\d+\.?\d*)/, - ] - const re = new RegExp(coordPatterns.map(p => p.source).join('|'), 'g') + const coordPatterns = /(-?\d+\.?\d*)([,\x2F\uFF0C])(-?\d+\.?\d*)/ + const re = new RegExp(coordPatterns, 'g') htmlHolder.querySelectorAll('p') .forEach(p => { replaceTextNodes(p, re, match => { -- cgit v1.2.3-70-g09d2 From 5502bf29bdbaa054a96794ddf93ab8cf0bcc2f77 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Thu, 17 Oct 2024 10:19:46 +0800 Subject: fix: CRS for addon --- addon/index.mjs | 1 + addon/manifest.json | 5 +++-- src/dumbymap.mjs | 7 +++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/addon/index.mjs b/addon/index.mjs index 323edf1..2494ec4 100644 --- a/addon/index.mjs +++ b/addon/index.mjs @@ -12,6 +12,7 @@ const simpleRender = window.mapclay.renderWith(config => ({ })) window.generateMaps(document.querySelector('main') ?? document.body, { + crs: url.searchParams.get('crs') ?? 'EPSG:4326', initialLayout: '', render: simpleRender, }) diff --git a/addon/manifest.json b/addon/manifest.json index e97ae50..2d7b1ed 100644 --- a/addon/manifest.json +++ b/addon/manifest.json @@ -12,7 +12,7 @@ "content_scripts": [ { "matches": [ - "*://*.mozilla.org/*", + "*://developer.mozilla.org/*", "*://hackmd.io/*", "*://*.ptt.cc/*" ], @@ -29,6 +29,7 @@ "permissions": [ "activeTab", "tabs", - "scripting" + "scripting", + "https://epsg.io/*" ] } diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 55d29d3..cbd44b2 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs @@ -241,10 +241,10 @@ export const generateMaps = (container, { register(proj4) fromEPSGCode(crs).then(() => resolve()) }) - const addGeoSchemeByText = new Promise(resolve => { + const addGeoSchemeByText = (async () => { const coordPatterns = /(-?\d+\.?\d*)([,\x2F\uFF0C])(-?\d+\.?\d*)/ const re = new RegExp(coordPatterns, 'g') - htmlHolder.querySelectorAll('p') + htmlHolder.querySelectorAll('.dumby-block') .forEach(p => { replaceTextNodes(p, re, match => { const a = document.createElement('a') @@ -253,8 +253,7 @@ export const generateMaps = (container, { return a }) }) - resolve() - }) + })() Promise.all([setCRS, addGeoSchemeByText]).then(() => { Array.from(container.querySelectorAll(geoLinkSelector)) -- cgit v1.2.3-70-g09d2 From 62b7af8ce0ccbad26cd00be24cc2cf1e817b8581 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Thu, 17 Oct 2024 10:26:52 +0800 Subject: feat: more precise way to get htmlHolder and blocks --- addon/index.mjs | 25 ++++++++++++++++++++++++- src/dumbymap.mjs | 5 ++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/addon/index.mjs b/addon/index.mjs index 2494ec4..7f33fc5 100644 --- a/addon/index.mjs +++ b/addon/index.mjs @@ -1,4 +1,26 @@ -const { Leaflet } = window.mapclay.renderers +const url = new URL(window.location) +if (url.host === 'www.ptt.cc') { + const content = document.querySelector('#main-content') + Array.from(content.childNodes) + .filter(n => !(n instanceof window.HTMLElement)) + .forEach(text => { + const span = document.createElement('span') + span.innerText = text.textContent + text.replaceWith(span) + }) +} + +const blockSelectors = { + 'developer.mozilla': '.section-content', + 'hackmd.io': '#doc > *', + 'www.ptt.cc': '#main-content > span', +} +const blockSelector = blockSelectors[url.host] + +const addBlocks = blockSelector + ? root => Array.from(root.querySelectorAll(blockSelector)) + : undefined + const simpleRender = window.mapclay.renderWith(config => ({ use: 'Leaflet', width: '100%', @@ -13,6 +35,7 @@ const simpleRender = window.mapclay.renderWith(config => ({ window.generateMaps(document.querySelector('main') ?? document.body, { crs: url.searchParams.get('crs') ?? 'EPSG:4326', + addBlocks, initialLayout: '', render: simpleRender, }) diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index cbd44b2..94fcc1d 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs @@ -171,8 +171,11 @@ export const generateMaps = (container, { container.dataset.layout = initialLayout ?? defaultLayouts[0].name /** Prepare Semantic HTML part and blocks of contents inside */ - const htmlHolder = container.querySelector('.SemanticHtml, :has(article, section)') ?? container.firstElementChild + const htmlHolder = container.querySelector('.SemanticHtml') ?? + Array.from(container.children).find(e => e.id?.includes('main') || e.className.includes('main')) ?? + Array.from(container.children).sort((a, b) => a.textContent.length < b.textContent.length).at(0) htmlHolder.classList.add('.SemanticHtml') + const blocks = addBlocks(htmlHolder) blocks.forEach(b => { b.classList.add('dumby-block') -- cgit v1.2.3-70-g09d2 From e4f01ea8f7817fa738ea9012fa217a2b9eca88aa Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Thu, 17 Oct 2024 10:27:25 +0800 Subject: feat: add other default renderers --- addon/index.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/index.mjs b/addon/index.mjs index 7f33fc5..092adc4 100644 --- a/addon/index.mjs +++ b/addon/index.mjs @@ -28,7 +28,7 @@ const simpleRender = window.mapclay.renderWith(config => ({ XYZ: 'https://tile.openstreetmap.jp/styles/osm-bright/512/{z}/{x}/{y}.png', ...config, aliases: { - use: { Leaflet }, + use: window.mapclay.renderers, ...(config.aliases ?? {}), }, })) -- cgit v1.2.3-70-g09d2 From 337a562ee8c9e2531a1a6799acaa66567ad7ef12 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Thu, 17 Oct 2024 10:28:32 +0800 Subject: feat: option "autoMap" in case no valid render target in Semantic HTML --- addon/index.mjs | 1 + src/dumbymap.mjs | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/addon/index.mjs b/addon/index.mjs index 092adc4..b5d71ba 100644 --- a/addon/index.mjs +++ b/addon/index.mjs @@ -38,4 +38,5 @@ window.generateMaps(document.querySelector('main') ?? document.body, { addBlocks, initialLayout: '', render: simpleRender, + autoMap: true, }) diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 94fcc1d..706e874 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs @@ -14,7 +14,7 @@ import { register, fromEPSGCode } from 'ol/proj/proj4' import LeaderLine from 'leader-line' /** CSS Selector for main components */ -const mapBlockSelector = 'pre:has(.language-map)' +const mapBlockSelector = 'pre:has(.language-map), .mapclay-container' const docLinkSelector = 'a[href^="#"][title^="=>"]' const geoLinkSelector = 'a[href^="geo:"]' @@ -163,6 +163,7 @@ export const generateMaps = (container, { delay, renderCallback, addBlocks = defaultBlocks, + autoMap = false, render = defaultRender, } = {}) => { /** Prepare Contaner */ @@ -457,11 +458,12 @@ export const generateMaps = (container, { const elementsWithMapConfig = Array.from( container.querySelectorAll(mapBlockSelector) ?? [], ) - if (elementsWithMapConfig.length === 0) { - const map = document.createElement('pre') - map.textContent = '#Created by DumbyMap' - htmlHolder.insertBefore(map, htmlHolder.firstElementChild) - elementsWithMapConfig.push(map) + if (autoMap && elementsWithMapConfig.length === 0) { + const mapContainer = document.createElement('pre') + mapContainer.className = 'mapclay-container' + mapContainer.textContent = '#Created by DumbyMap' + htmlHolder.insertBefore(mapContainer, htmlHolder.firstElementChild) + elementsWithMapConfig.push(mapContainer) } /** Render each taget element for maps */ -- cgit v1.2.3-70-g09d2 From 5b1e0f50415fd7834b467e18859c0bd789c646a9 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Thu, 17 Oct 2024 10:31:08 +0800 Subject: style: standardjs --- scripts/rollup.config.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/rollup.config.js b/scripts/rollup.config.js index 7dc9f75..434bd85 100644 --- a/scripts/rollup.config.js +++ b/scripts/rollup.config.js @@ -81,11 +81,12 @@ export default [ .filter(config => { if (addon) return config.input.match(/dumbymap/) if (!prod) return config.input.match(/editor/) + return true }) .map(config => { if (!addon) return config - config.output.forEach(o => o.dir = './addon') + config.output.forEach(o => { o.dir = './addon' }) config.plugins.push({ name: 'remove-exports', transform (code, id) { -- cgit v1.2.3-70-g09d2 From 9a66411258781a57d5c953b7113403fdf0d218cf Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Thu, 17 Oct 2024 10:31:22 +0800 Subject: feat: add utils for finding common ancestor --- src/utils.mjs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/utils.mjs b/src/utils.mjs index 1fe3ce5..327bee4 100644 --- a/src/utils.mjs +++ b/src/utils.mjs @@ -177,3 +177,35 @@ export const replaceTextNodes = ( node = nodeIterator.nextNode() } } + +/** + * Get the common ancestor of two or more elements + * {@link https://gist.github.com/kieranbarker/cd86310d0782b7c52ce90cd7f45bb3eb} + * @param {String} selector A valid CSS selector + * @returns {Element} The common ancestor + */ +export function getCommonAncestor (selector) { + // Get the elements matching the selector + const elems = document.querySelectorAll(selector) + + // If there are no elements, return null + if (elems.length < 1) return null + + // If there's only one element, return it + if (elems.length < 2) return elems[0] + + // Otherwise, create a new Range + const range = document.createRange() + + // Start at the beginning of the first element + range.setStart(elems[0], 0) + + // Stop at the end of the last element + range.setEnd( + elems[elems.length - 1], + elems[elems.length - 1].childNodes.length, + ) + + // Return the common ancestor + return range.commonAncestorContainer +} -- cgit v1.2.3-70-g09d2