diff options
Diffstat (limited to 'src/dumbymap.mjs')
-rw-r--r-- | src/dumbymap.mjs | 78 |
1 files changed, 26 insertions, 52 deletions
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 81a65ca..4329bbf 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs | |||
@@ -4,7 +4,7 @@ import MarkdownItFootnote from 'markdown-it-footnote' | |||
4 | import MarkdownItFrontMatter from 'markdown-it-front-matter' | 4 | import MarkdownItFrontMatter from 'markdown-it-front-matter' |
5 | import MarkdownItInjectLinenumbers from 'markdown-it-inject-linenumbers' | 5 | import MarkdownItInjectLinenumbers from 'markdown-it-inject-linenumbers' |
6 | import { renderWith, defaultAliases, parseConfigsFromYaml } from 'mapclay' | 6 | import { renderWith, defaultAliases, parseConfigsFromYaml } from 'mapclay' |
7 | import { onRemove, animateRectTransition, throttle, shiftByWindow } from './utils' | 7 | import { onRemove, animateRectTransition, throttle, shiftByWindow, replaceTextNodes } from './utils' |
8 | import { Layout, SideBySide, Overlay } from './Layout' | 8 | import { Layout, SideBySide, Overlay } from './Layout' |
9 | import * as utils from './dumbyUtils' | 9 | import * as utils from './dumbyUtils' |
10 | import * as menuItem from './MenuItem' | 10 | import * as menuItem from './MenuItem' |
@@ -56,27 +56,6 @@ export const markdown2HTML = (container, mdContent) => { | |||
56 | .use(MarkdownItFrontMatter) | 56 | .use(MarkdownItFrontMatter) |
57 | .use(MarkdownItInjectLinenumbers) | 57 | .use(MarkdownItInjectLinenumbers) |
58 | 58 | ||
59 | /** Set up linkify for GeoLinks */ | ||
60 | const coordinateRegex = /^(\D*)(-?\d+\.?\d*)\s*([,\x2F\uFF0C])\s*(-?\d+\.?\d*)/ | ||
61 | const coordinateValue = { | ||
62 | validate: coordinateRegex, | ||
63 | normalize: function (match) { | ||
64 | const [, , x, sep, y] = match.text.match(coordinateRegex) | ||
65 | match.url = `geo:${y},${x}` | ||
66 | match.text = `${x}${sep}${y}` | ||
67 | match.index += match.text.indexOf(x) + 1 | ||
68 | return match | ||
69 | }, | ||
70 | } | ||
71 | const patterns = ['[', '(', '📍', '\uFF08', '@', 'twd'] | ||
72 | patterns.forEach(prefix => | ||
73 | md.linkify.add(prefix, coordinateValue), | ||
74 | ) | ||
75 | md.linkify.add('geo:', { | ||
76 | validate: /(-?\d+\.?\d*),(-?\d+\.?\d*)/, | ||
77 | normalize: match => match, | ||
78 | }) | ||
79 | |||
80 | /** Custom rule for Blocks in DumbyMap */ | 59 | /** Custom rule for Blocks in DumbyMap */ |
81 | // FIXME A better way to generate blocks | 60 | // FIXME A better way to generate blocks |
82 | md.renderer.rules.dumby_block_open = () => '<div>' | 61 | md.renderer.rules.dumby_block_open = () => '<div>' |
@@ -130,7 +109,7 @@ export const generateMaps = (container, { | |||
130 | 109 | ||
131 | const htmlHolder = container.querySelector('.SemanticHtml') ?? container | 110 | const htmlHolder = container.querySelector('.SemanticHtml') ?? container |
132 | const blocks = addBlocks(htmlHolder) | 111 | const blocks = addBlocks(htmlHolder) |
133 | blocks.forEach(b => b.dataset.total = blocks.length) | 112 | blocks.forEach(b => { b.dataset.total = blocks.length }) |
134 | 113 | ||
135 | const showcase = document.createElement('div') | 114 | const showcase = document.createElement('div') |
136 | container.appendChild(showcase) | 115 | container.appendChild(showcase) |
@@ -189,37 +168,32 @@ export const generateMaps = (container, { | |||
189 | }) | 168 | }) |
190 | 169 | ||
191 | /** LINK: Set CRS and GeoLinks */ | 170 | /** LINK: Set CRS and GeoLinks */ |
192 | register(proj4) | 171 | const setCRS = new Promise(resolve => { |
193 | fromEPSGCode(crs).then(projection => { | 172 | register(proj4) |
194 | const transform = proj4(crs, 'EPSG:4326').forward | 173 | fromEPSGCode(crs).then(() => resolve()) |
174 | }) | ||
175 | const addGeoSchemeByText = new Promise(resolve => { | ||
176 | const coordPatterns = [ | ||
177 | /[\x28\x5B\uFF08]\D*(-?\d+\.?\d*)([\x2F\s])(-?\d+\.?\d*)\D*[\x29\x5D\uFF09]/, | ||
178 | /(-?\d+\.?\d*)([,\uFF0C]\s?)(-?\d+\.?\d*)/, | ||
179 | ] | ||
180 | const re = new RegExp(coordPatterns.map(p => p.source).join('|'), 'g') | ||
181 | htmlHolder.querySelectorAll('p') | ||
182 | .forEach(p => { | ||
183 | replaceTextNodes(p, re, match => { | ||
184 | const a = document.createElement('a') | ||
185 | a.href = `geo:0,0?xy=${match.at(1)},${match.at(3)}` | ||
186 | a.textContent = match.at(0) | ||
187 | return a | ||
188 | }) | ||
189 | }) | ||
190 | resolve() | ||
191 | }) | ||
195 | 192 | ||
193 | Promise.all([setCRS, addGeoSchemeByText]).then(() => { | ||
196 | Array.from(container.querySelectorAll(geoLinkSelector)) | 194 | Array.from(container.querySelectorAll(geoLinkSelector)) |
197 | .map(link => { | 195 | .map(utils.setGeoSchemeByCRS(crs)) |
198 | // set coordinate as lat/lon in WGS84 | 196 | .filter(link => link instanceof window.HTMLAnchorElement) |
199 | const params = new URLSearchParams(link.search) | ||
200 | const [y, x] = link.href | ||
201 | .match(utils.coordPattern) | ||
202 | .splice(1) | ||
203 | .map(Number) | ||
204 | const [lon, lat] = transform([x, y]) | ||
205 | .map(value => parseFloat(value.toFixed(6))) | ||
206 | link.href = `geo:${lat},${lon}` | ||
207 | |||
208 | // set query strings | ||
209 | params.set('xy', `${x},${y}`) | ||
210 | params.set('crs', crs) | ||
211 | params.set('q', `${lat},${lon}`) | ||
212 | link.search = params | ||
213 | |||
214 | if (projection.getUnits() === 'degrees' && | ||
215 | (lon > 180 || lon < -180 || lat > 90 || lat < -90) | ||
216 | ) { | ||
217 | link.dataset.valid = false | ||
218 | link.title = `Invalid Coordinate, maybe try another crs other than ${crs}` | ||
219 | } | ||
220 | |||
221 | return link | ||
222 | }) | ||
223 | .forEach(utils.createGeoLink) | 197 | .forEach(utils.createGeoLink) |
224 | }) | 198 | }) |
225 | 199 | ||