@story-map/remark-story-map 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +217 -14
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +43 -21
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -6
- package/dist/index.js.map +1 -1
- package/dist/vault.d.ts +11 -3
- package/dist/vault.d.ts.map +1 -1
- package/dist/vault.js +87 -38
- package/dist/vault.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,27 +1,194 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @story-map/remark-story-map
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Build-time Remark adapter and browser client for publishing StoryMap fenced
|
|
4
|
+
blocks (` ```story-map `) in a Docusaurus site.
|
|
5
|
+
|
|
6
|
+
At build time the plugin parses each fenced block with `story-map-core`,
|
|
7
|
+
optionally resolves notes from a Vault, and replaces the block with a
|
|
8
|
+
`.story-map-host[data-story-map-config]` placeholder. No Leaflet map is created
|
|
9
|
+
during the Node/SSR build. In the browser, the client entry mounts the shared
|
|
10
|
+
`@story-map/react-story-map` renderer into every host, including after
|
|
11
|
+
Docusaurus SPA navigation.
|
|
12
|
+
|
|
13
|
+
- Build entry: `@story-map/remark-story-map` (Node APIs allowed).
|
|
14
|
+
- Browser entry: `@story-map/remark-story-map/client` (no Node APIs).
|
|
15
|
+
- Route/slug policy stays with the host; this package never implements
|
|
16
|
+
Docusaurus slug rules.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add @story-map/remark-story-map react@^19 react-dom@^19
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The renderer is pulled in transitively, but the host site is responsible for
|
|
25
|
+
providing `react` / `react-dom` (declared as peer dependencies).
|
|
26
|
+
Both peers must be React 19. A Docusaurus installation using React 18 does not satisfy
|
|
27
|
+
these peer requirements; verify the site's versions before integrating. Build-time
|
|
28
|
+
usage is ESM and the release workflow verifies Node 24 imports. A full Docusaurus site
|
|
29
|
+
build and browser smoke test remain host integration checks.
|
|
4
30
|
|
|
5
31
|
## Docusaurus setup
|
|
6
32
|
|
|
7
|
-
|
|
33
|
+
Register the transformer in the docs and/or blog options. The same plugin
|
|
34
|
+
instance can be used for both:
|
|
8
35
|
|
|
9
36
|
```js
|
|
10
37
|
import remarkStoryMap from '@story-map/remark-story-map';
|
|
11
38
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
39
|
+
const storyMapOptions = {
|
|
40
|
+
vaultRoot: '/absolute/path/to/vault',
|
|
41
|
+
assetBase: '/vault-assets',
|
|
42
|
+
resolveNoteHref: (vaultRelativePath) => {
|
|
43
|
+
// See "Resolving published note routes" below.
|
|
44
|
+
return undefined;
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export default {
|
|
49
|
+
presets: [
|
|
50
|
+
[
|
|
51
|
+
'classic',
|
|
52
|
+
{
|
|
53
|
+
docs: {
|
|
54
|
+
remarkPlugins: [[remarkStoryMap, storyMapOptions]],
|
|
55
|
+
},
|
|
56
|
+
blog: {
|
|
57
|
+
remarkPlugins: [[remarkStoryMap, storyMapOptions]],
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
],
|
|
62
|
+
plugins: ['./plugins/story-map-client'],
|
|
63
|
+
};
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Blog support uses the same adapter; only add it when a real blog StoryMap use
|
|
67
|
+
case exists.
|
|
68
|
+
|
|
69
|
+
## Options
|
|
70
|
+
|
|
71
|
+
| Option | Type | Purpose |
|
|
72
|
+
| --- | --- | --- |
|
|
73
|
+
| `vaultRoot` | `string` | Vault/repo root to index. Required for explicit `slide.note` WikiLinks and recursive `noteFolder` discovery. |
|
|
74
|
+
| `assetBase` | `string` | URL prefix that rewrites resolved Vault-relative media paths (for example `/vault-assets`). It only rewrites URLs; it does not copy files. |
|
|
75
|
+
| `resolveNoteHref` | `(vaultRelativePath: string) => string \| undefined` | Host callback that maps a Vault-relative note path (without `.md`) to its final published href. Used by `noteDisplay: link`. |
|
|
76
|
+
|
|
77
|
+
`vaultRelativePath` is the note's Vault-relative path without the extension,
|
|
78
|
+
using forward slashes, for example `Trips/Santiago`.
|
|
79
|
+
|
|
80
|
+
When `vaultRoot` is omitted, fenced blocks are parsed and serialized, but no
|
|
81
|
+
note or `noteFolder` resolution happens.
|
|
82
|
+
|
|
83
|
+
## Resolving published note routes
|
|
84
|
+
|
|
85
|
+
`resolveNoteHref` lets the host decide published URLs. The `kywk.github.io`
|
|
86
|
+
site already owns this decision through `scripts/content-links.js`, which
|
|
87
|
+
exports `createContentLinkIndex({ root, docsConfig, blogConfig })`. Its index
|
|
88
|
+
exposes `resolve(name)`, returning an array of entries with a `.route`
|
|
89
|
+
property. Wire the callback to that existing index instead of reimplementing
|
|
90
|
+
slug logic:
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
import { createContentLinkIndex } from './scripts/content-links.js';
|
|
94
|
+
|
|
95
|
+
const contentLinkIndex = createContentLinkIndex({
|
|
96
|
+
root: vaultRoot,
|
|
97
|
+
docsConfig,
|
|
98
|
+
blogConfig,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const storyMapOptions = {
|
|
102
|
+
vaultRoot,
|
|
103
|
+
assetBase: '/vault-assets',
|
|
104
|
+
resolveNoteHref: (vaultRelativePath) => {
|
|
105
|
+
const matches = contentLinkIndex.resolve(vaultRelativePath);
|
|
106
|
+
return matches.length === 1 ? matches[0].route : undefined;
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Rules enforced by the package:
|
|
112
|
+
|
|
113
|
+
- `resolveNoteHref` is only consulted for `noteDisplay: link`.
|
|
114
|
+
- A returned string becomes `StorySlide.notePath`, which the renderer turns
|
|
115
|
+
into a normal browser link.
|
|
116
|
+
- `undefined` (or an ambiguous multiple-match result) leaves the slide title
|
|
117
|
+
unlinked; the build does not invent a route.
|
|
118
|
+
- No absolute local filesystem path is ever serialized into the HTML.
|
|
119
|
+
|
|
120
|
+
Do not copy `deriveSlug()` or any Docusaurus URL normalization into the
|
|
121
|
+
package or the site's StoryMap config; keep the existing
|
|
122
|
+
`scripts/content-links.js` / `remark-slug-normalizer` pipeline as the single
|
|
123
|
+
URL authority.
|
|
124
|
+
|
|
125
|
+
## Note resolution
|
|
126
|
+
|
|
127
|
+
With `vaultRoot` configured, notes are indexed recursively. The scanner skips
|
|
128
|
+
dot-directories, `node_modules`, `build`, `dist`, and `coverage`.
|
|
129
|
+
|
|
130
|
+
### Explicit slides
|
|
131
|
+
|
|
132
|
+
A slide with `note: "[[Trips/Santiago]]"` inherits note frontmatter
|
|
133
|
+
(`title`, `description`/`summary`, `location`, `cover`/`image`/`media`,
|
|
134
|
+
`mapmarker`). Explicit slide properties override note-derived values, and
|
|
135
|
+
explicit slides keep their author order exactly: they are never appended to or
|
|
136
|
+
reordered by folder discovery. A WikiLink matching multiple notes without an
|
|
137
|
+
explicit path is a build-time error; use a Vault-relative path.
|
|
138
|
+
|
|
139
|
+
### `noteFolder`
|
|
140
|
+
|
|
141
|
+
`noteFolder` names one Vault-relative folder (subfolders are included
|
|
142
|
+
recursively). Order is controlled only by:
|
|
143
|
+
|
|
144
|
+
- `order: asc | desc` (default `asc`);
|
|
145
|
+
- `dateField` (default `date-created`).
|
|
146
|
+
|
|
147
|
+
Only notes whose frontmatter contains `story-map-note: true` are discovered;
|
|
148
|
+
other Markdown files in the folder are ignored. Notes without a parseable date
|
|
149
|
+
sort last.
|
|
150
|
+
|
|
151
|
+
```yaml
|
|
152
|
+
noteFolder: Trips/Santiago
|
|
153
|
+
order: desc
|
|
154
|
+
dateField: date-created
|
|
19
155
|
```
|
|
20
156
|
|
|
21
|
-
|
|
157
|
+
## `noteDisplay`
|
|
158
|
+
|
|
159
|
+
Note presentation is controlled by `noteDisplay`, which accepts:
|
|
160
|
+
|
|
161
|
+
- `basic` — frontmatter-derived content only.
|
|
162
|
+
- `link` — frontmatter basics plus a host-resolved `notePath` when
|
|
163
|
+
`resolveNoteHref` returns a string. This is the default.
|
|
164
|
+
- `full` — frontmatter basics plus the frontmatter-stripped note Markdown body
|
|
165
|
+
as slide text.
|
|
166
|
+
|
|
167
|
+
`link` is platform-specific only at navigation time: Docusaurus resolves the
|
|
168
|
+
published route and the renderer emits a normal browser link.
|
|
169
|
+
|
|
170
|
+
## Media resolution
|
|
171
|
+
|
|
172
|
+
Relative media is resolved against the correct source document:
|
|
173
|
+
|
|
174
|
+
- note-derived media resolves relative to the note file;
|
|
175
|
+
- media authored explicitly on a slide resolves relative to the StoryMap source
|
|
176
|
+
Markdown document.
|
|
177
|
+
|
|
178
|
+
Absolute `http:`/`https:`/`data:`/`blob:` URLs are left unchanged. When
|
|
179
|
+
`assetBase` is set, resolved Vault-relative paths are rewritten to
|
|
180
|
+
`<assetBase>/<path>` for the browser.
|
|
181
|
+
|
|
182
|
+
`assetBase` only rewrites URLs. Copying Vault attachments into the Docusaurus
|
|
183
|
+
static directory remains part of the site's own publishing pipeline; the
|
|
184
|
+
package never copies files.
|
|
185
|
+
|
|
186
|
+
## Registering the browser client
|
|
187
|
+
|
|
188
|
+
Docusaurus client modules are registered by a small local plugin. See
|
|
189
|
+
`examples/docusaurus/story-map-client-plugin.cjs`:
|
|
22
190
|
|
|
23
191
|
```js
|
|
24
|
-
// plugins/story-map-client/index.js
|
|
25
192
|
module.exports = function storyMapClientPlugin() {
|
|
26
193
|
return {
|
|
27
194
|
name: 'story-map-client',
|
|
@@ -32,6 +199,42 @@ module.exports = function storyMapClientPlugin() {
|
|
|
32
199
|
};
|
|
33
200
|
```
|
|
34
201
|
|
|
35
|
-
|
|
202
|
+
Add `./plugins/story-map-client` (or the equivalent path) to the site's
|
|
203
|
+
`plugins` list. The client entry only initializes maps in the browser,
|
|
204
|
+
mounts every host on the page, skips duplicate mounts, unmounts roots whose
|
|
205
|
+
host nodes were removed during SPA navigation, and keeps Node APIs out of the
|
|
206
|
+
browser bundle.
|
|
207
|
+
|
|
208
|
+
## Docusaurus theme bridge
|
|
36
209
|
|
|
37
|
-
|
|
210
|
+
The generic renderer owns the StoryMap semantic CSS variables. The Docusaurus
|
|
211
|
+
site maps Infima variables onto them via a host stylesheet, not inside the
|
|
212
|
+
renderer. Copy `examples/docusaurus/story-map-theme.css` into the site and
|
|
213
|
+
load it through the Docusaurus stylesheet chain:
|
|
214
|
+
|
|
215
|
+
```css
|
|
216
|
+
.story-map-host {
|
|
217
|
+
--story-map-bg: var(--ifm-background-surface-color);
|
|
218
|
+
--story-map-fg: var(--ifm-font-color-base);
|
|
219
|
+
--story-map-muted: var(--ifm-color-emphasis-700);
|
|
220
|
+
--story-map-border: var(--ifm-color-emphasis-300);
|
|
221
|
+
--story-map-accent: var(--ifm-color-primary);
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
This keeps panel, text, border, buttons, and links readable in light and dark
|
|
226
|
+
themes. Dynamic light/dark tile provider switching is deferred; the goal is
|
|
227
|
+
readable, theme-compatible StoryMap chrome/panel content.
|
|
228
|
+
|
|
229
|
+
## How the pipeline fits together
|
|
230
|
+
|
|
231
|
+
```text
|
|
232
|
+
story-map fenced block
|
|
233
|
+
-> remark-story-map (build-time, Node)
|
|
234
|
+
-> VaultIndex (explicit notes / noteFolder)
|
|
235
|
+
-> host resolveNoteHref(vaultRelativePath)
|
|
236
|
+
-> existing contentLinkIndex / published route
|
|
237
|
+
-> serialized StoryMapConfig in .story-map-host
|
|
238
|
+
-> browser StoryMap client
|
|
239
|
+
-> shared @story-map/react-story-map renderer (Leaflet imported client-side)
|
|
240
|
+
```
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":"AAEA,OAAO,0BAA0B,CAAC;AAClC,OAAO,uCAAuC,CAAC;AAwC/C,wBAAgB,cAAc,CAAC,KAAK,GAAE,UAAqB,QAI1D;AAED,wBAAgB,mBAAmB,eAQlC"}
|
package/dist/client.js
CHANGED
|
@@ -1,34 +1,56 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { createRoot } from 'react-dom/client';
|
|
3
|
-
import { StoryMap } from '@story-map/react-story-map';
|
|
4
3
|
import 'leaflet/dist/leaflet.css';
|
|
5
4
|
import '@story-map/react-story-map/styles.css';
|
|
6
|
-
const roots = new
|
|
5
|
+
const roots = new Map();
|
|
6
|
+
const pending = new Set();
|
|
7
|
+
let rendererPromise;
|
|
8
|
+
function loadRenderer() {
|
|
9
|
+
rendererPromise ??= import('@story-map/react-story-map');
|
|
10
|
+
return rendererPromise;
|
|
11
|
+
}
|
|
12
|
+
async function mountHost(host) {
|
|
13
|
+
if (roots.has(host) || pending.has(host))
|
|
14
|
+
return;
|
|
15
|
+
const raw = host.dataset.storyMapConfig;
|
|
16
|
+
if (!raw)
|
|
17
|
+
return;
|
|
18
|
+
pending.add(host);
|
|
19
|
+
try {
|
|
20
|
+
const story = JSON.parse(decodeURIComponent(raw));
|
|
21
|
+
const { StoryMap } = await loadRenderer();
|
|
22
|
+
if (roots.has(host) || !host.isConnected)
|
|
23
|
+
return;
|
|
24
|
+
const root = createRoot(host);
|
|
25
|
+
root.render(_jsx(StoryMap, { story: story }));
|
|
26
|
+
roots.set(host, root);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
host.textContent = error instanceof Error ? `StoryMap error: ${error.message}` : 'StoryMap error';
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
pending.delete(host);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function unmountRemovedHosts() {
|
|
36
|
+
for (const [host, root] of roots) {
|
|
37
|
+
if (host.isConnected)
|
|
38
|
+
continue;
|
|
39
|
+
roots.delete(host);
|
|
40
|
+
queueMicrotask(() => root.unmount());
|
|
41
|
+
}
|
|
42
|
+
}
|
|
7
43
|
export function mountStoryMaps(scope = document) {
|
|
44
|
+
unmountRemovedHosts();
|
|
8
45
|
const hosts = scope.querySelectorAll('[data-story-map-config]');
|
|
9
|
-
hosts.forEach((host) =>
|
|
10
|
-
if (roots.has(host))
|
|
11
|
-
return;
|
|
12
|
-
const raw = host.dataset.storyMapConfig;
|
|
13
|
-
if (!raw)
|
|
14
|
-
return;
|
|
15
|
-
try {
|
|
16
|
-
const story = JSON.parse(decodeURIComponent(raw));
|
|
17
|
-
const root = createRoot(host);
|
|
18
|
-
root.render(_jsx(StoryMap, { story: story }));
|
|
19
|
-
roots.set(host, root);
|
|
20
|
-
}
|
|
21
|
-
catch (error) {
|
|
22
|
-
host.textContent = error instanceof Error ? `StoryMap error: ${error.message}` : 'StoryMap error';
|
|
23
|
-
}
|
|
24
|
-
});
|
|
46
|
+
hosts.forEach((host) => void mountHost(host));
|
|
25
47
|
}
|
|
26
48
|
export function startStoryMapClient() {
|
|
27
49
|
if (typeof document === 'undefined')
|
|
28
50
|
return () => { };
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
const observer = new MutationObserver(
|
|
51
|
+
const run = () => mountStoryMaps(document);
|
|
52
|
+
run();
|
|
53
|
+
const observer = new MutationObserver(run);
|
|
32
54
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
33
55
|
return () => observer.disconnect();
|
|
34
56
|
}
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,kBAAkB,CAAC;AAEzD,OAAO,0BAA0B,CAAC;AAClC,OAAO,uCAAuC,CAAC;AAE/C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAiB,CAAC;AACvC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAW,CAAC;AACnC,IAAI,eAAiF,CAAC;AAEtF,SAAS,YAAY;IACnB,eAAe,KAAK,MAAM,CAAC,4BAA4B,CAAC,CAAC;IACzD,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,IAAiB;IACxC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IACjD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;IACxC,IAAI,CAAC,GAAG;QAAE,OAAO;IAEjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAmB,CAAC;QACpE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,YAAY,EAAE,CAAC;QAC1C,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QAEjD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,KAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,GAAI,CAAC,CAAC;QACxC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,WAAW,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,mBAAmB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC;IACpG,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB;IAC1B,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,WAAW;YAAE,SAAS;QAC/B,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACnB,cAAc,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAK,GAAe,QAAQ;IACzD,mBAAmB,EAAE,CAAC;IACtB,MAAM,KAAK,GAAG,KAAK,CAAC,gBAAgB,CAAc,yBAAyB,CAAC,CAAC;IAC7E,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAErD,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC3C,GAAG,EAAE,CAAC;IACN,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC3C,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;AACrC,CAAC;AAED,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;IACpC,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACtC,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,mBAAmB,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7F,CAAC;SAAM,CAAC;QACN,mBAAmB,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import type { Root } from 'mdast';
|
|
2
|
+
export declare const STORY_MAP_FENCE = "story-map";
|
|
2
3
|
export interface RemarkStoryMapOptions {
|
|
3
4
|
vaultRoot?: string;
|
|
4
5
|
assetBase?: string;
|
|
6
|
+
resolveNoteHref?: (vaultRelativePath: string) => string | undefined;
|
|
7
|
+
}
|
|
8
|
+
export default function remarkStoryMap(options?: RemarkStoryMapOptions): (tree: Root, file?: RemarkVFile) => void;
|
|
9
|
+
interface RemarkVFile {
|
|
10
|
+
path?: string;
|
|
11
|
+
data?: {
|
|
12
|
+
frontMatter?: Record<string, unknown>;
|
|
13
|
+
};
|
|
5
14
|
}
|
|
6
|
-
export default function remarkStoryMap(options?: RemarkStoryMapOptions): (tree: Root) => void;
|
|
7
15
|
export { VaultIndex } from './vault.js';
|
|
8
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,IAAI,EAAE,MAAM,OAAO,CAAC;AAK9C,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,IAAI,EAAE,MAAM,OAAO,CAAC;AAK9C,eAAO,MAAM,eAAe,cAAc,CAAC;AAE3C,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CACrE;AAED,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,OAAO,GAAE,qBAA0B,UAS1D,IAAI,SAAS,WAAW,UAqBvC;AAED,UAAU,WAAW;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QACL,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACvC,CAAC;CACH;AAMD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
import { visit } from 'unist-util-visit';
|
|
2
|
-
import {
|
|
2
|
+
import { parseStoryMapSourceYaml, toStoryMapConfig } from '@story-map/story-map-core';
|
|
3
3
|
import { VaultIndex } from './vault.js';
|
|
4
|
+
export const STORY_MAP_FENCE = 'story-map';
|
|
4
5
|
export default function remarkStoryMap(options = {}) {
|
|
5
6
|
const vault = options.vaultRoot
|
|
6
7
|
? new VaultIndex({
|
|
7
8
|
vaultRoot: options.vaultRoot,
|
|
8
9
|
...(options.assetBase ? { assetBase: options.assetBase } : {}),
|
|
10
|
+
...(options.resolveNoteHref ? { resolveNoteHref: options.resolveNoteHref } : {}),
|
|
9
11
|
})
|
|
10
12
|
: undefined;
|
|
11
|
-
return (tree) => {
|
|
13
|
+
return (tree, file) => {
|
|
14
|
+
const sourcePath = typeof file?.path === 'string' ? file.path : undefined;
|
|
15
|
+
const isDocument = file?.data?.frontMatter?.['story-map'] === true;
|
|
16
|
+
const documentAttribute = isDocument ? ' data-story-map-document="true"' : '';
|
|
12
17
|
visit(tree, 'code', (node, index, parent) => {
|
|
13
|
-
if (node.lang !==
|
|
18
|
+
if (node.lang !== STORY_MAP_FENCE || index === undefined || !parent)
|
|
14
19
|
return;
|
|
15
|
-
const parsed =
|
|
16
|
-
const story = vault
|
|
20
|
+
const parsed = parseStoryMapSourceYaml(node.value);
|
|
21
|
+
const story = vault
|
|
22
|
+
? vault.resolveSource(parsed, sourcePath)
|
|
23
|
+
: toStoryMapConfig(parsed, parsed.slides ?? []);
|
|
17
24
|
const encoded = encodeURIComponent(JSON.stringify(story));
|
|
18
25
|
const html = {
|
|
19
26
|
type: 'html',
|
|
20
|
-
value: `<div class="story-map-host" data-story-map-config="${escapeAttribute(encoded)}"></div>`,
|
|
27
|
+
value: `<div class="story-map-host"${documentAttribute} data-story-map-config="${escapeAttribute(encoded)}"></div>`,
|
|
21
28
|
};
|
|
22
29
|
parent.children[index] = html;
|
|
23
30
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACtF,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CAAC;AAQ3C,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,OAAO,GAA0B,EAAE;IACxE,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS;QAC7B,CAAC,CAAC,IAAI,UAAU,CAAC;YACb,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjF,CAAC;QACJ,CAAC,CAAC,SAAS,CAAC;IAEd,OAAO,CAAC,IAAU,EAAE,IAAkB,EAAE,EAAE;QACxC,MAAM,UAAU,GAAG,OAAO,IAAI,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1E,MAAM,UAAU,GAAG,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;QACnE,MAAM,iBAAiB,GAAG,UAAU,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE9E,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAU,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAChD,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM;gBAAE,OAAO;YAE5E,MAAM,MAAM,GAAG,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnD,MAAM,KAAK,GAAG,KAAK;gBACjB,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC;gBACzC,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YAClD,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;YAC1D,MAAM,IAAI,GAAS;gBACjB,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,8BAA8B,iBAAiB,2BAA2B,eAAe,CAAC,OAAO,CAAC,UAAU;aACpH,CAAC;YAEF,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AASD,SAAS,eAAe,CAAC,KAAa;IACpC,OAAO,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAC1F,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/vault.d.ts
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
|
-
import { type StoryMapConfig } from '@story-map/story-map-core';
|
|
1
|
+
import { type StoryMapConfig, type StoryMapSourceConfig } from '@story-map/story-map-core';
|
|
2
2
|
export interface VaultResolveOptions {
|
|
3
3
|
vaultRoot: string;
|
|
4
4
|
assetBase?: string;
|
|
5
|
+
resolveNoteHref?: (vaultRelativePath: string) => string | undefined;
|
|
5
6
|
}
|
|
6
7
|
export declare class VaultIndex {
|
|
7
8
|
private readonly options;
|
|
8
9
|
private readonly byBasename;
|
|
9
10
|
private readonly byRelativePath;
|
|
11
|
+
private readonly notes;
|
|
10
12
|
constructor(options: VaultResolveOptions);
|
|
11
|
-
|
|
13
|
+
resolveSource(source: StoryMapSourceConfig, sourcePath?: string): StoryMapConfig;
|
|
14
|
+
resolveStory(story: StoryMapConfig, sourcePath?: string): StoryMapConfig;
|
|
15
|
+
private resolveExplicitSlides;
|
|
16
|
+
private resolveFolder;
|
|
17
|
+
private slideForNote;
|
|
12
18
|
private resolveSlide;
|
|
19
|
+
private applyNoteDisplay;
|
|
13
20
|
private resolveMedia;
|
|
14
|
-
private
|
|
21
|
+
private vaultRelativeDirectory;
|
|
22
|
+
private findIndexed;
|
|
15
23
|
private scan;
|
|
16
24
|
}
|
|
17
25
|
//# sourceMappingURL=vault.d.ts.map
|
package/dist/vault.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"AAGA,OAAO,EASL,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAI1B,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CACrE;AAUD,qBAAa,UAAU;IAKT,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA+B;IAC1D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAE3C,YAA6B,OAAO,EAAE,mBAAmB,EAExD;IAED,aAAa,CAAC,MAAM,EAAE,oBAAoB,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,cAAc,CAU/E;IAED,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,cAAc,CAEvE;IAED,OAAO,CAAC,qBAAqB;IAQ7B,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,YAAY;IAwBpB,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,IAAI;CA2Bb"}
|
package/dist/vault.js
CHANGED
|
@@ -1,77 +1,121 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import matter from 'gray-matter';
|
|
4
|
-
import {
|
|
4
|
+
import { isPathInFolder, mergeResolvedSlide, parseWikiLinkRef, slideFromNoteFrontmatter, sortNoteDates, stripFrontmatter, toStoryMapConfig, toTimestamp, } from '@story-map/story-map-core';
|
|
5
|
+
const EXCLUDED_DIRECTORIES = new Set(['node_modules', 'build', 'dist', 'coverage']);
|
|
5
6
|
export class VaultIndex {
|
|
6
7
|
options;
|
|
7
8
|
byBasename = new Map();
|
|
8
9
|
byRelativePath = new Map();
|
|
10
|
+
notes = [];
|
|
9
11
|
constructor(options) {
|
|
10
12
|
this.options = options;
|
|
11
13
|
this.scan(options.vaultRoot);
|
|
12
14
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
resolveSource(source, sourcePath) {
|
|
16
|
+
const noteDisplay = source.noteDisplay;
|
|
17
|
+
const explicitSlides = source.slides ?? [];
|
|
18
|
+
const slides = explicitSlides.length > 0
|
|
19
|
+
? this.resolveExplicitSlides(explicitSlides, sourcePath, noteDisplay)
|
|
20
|
+
: source.noteFolder
|
|
21
|
+
? this.resolveFolder(source.noteFolder, source.dateField, source.order, noteDisplay)
|
|
22
|
+
: [];
|
|
23
|
+
return toStoryMapConfig(source, slides);
|
|
24
|
+
}
|
|
25
|
+
resolveStory(story, sourcePath) {
|
|
26
|
+
return { ...story, slides: this.resolveExplicitSlides(story.slides, sourcePath, 'link') };
|
|
27
|
+
}
|
|
28
|
+
resolveExplicitSlides(slides, sourcePath, noteDisplay) {
|
|
29
|
+
return slides.map((slide) => this.resolveSlide(slide, sourcePath, noteDisplay));
|
|
30
|
+
}
|
|
31
|
+
resolveFolder(noteFolder, dateField, order, noteDisplay) {
|
|
32
|
+
const entries = this.notes
|
|
33
|
+
.filter((note) => isPathInFolder(note.relativePath, noteFolder))
|
|
34
|
+
.map((note) => ({
|
|
35
|
+
path: note.relativePath,
|
|
36
|
+
date: toTimestamp(note.frontmatter[dateField]),
|
|
37
|
+
note,
|
|
38
|
+
}))
|
|
39
|
+
.filter((entry) => entry.note.frontmatter['story-map-note'] === true);
|
|
40
|
+
return sortNoteDates(entries, order).map((entry) => this.slideForNote(entry.note, noteDisplay));
|
|
41
|
+
}
|
|
42
|
+
slideForNote(note, noteDisplay) {
|
|
43
|
+
const slide = {
|
|
44
|
+
...slideFromNoteFrontmatter(note.frontmatter, path.basename(note.relativePath)),
|
|
17
45
|
};
|
|
46
|
+
const media = slide.media
|
|
47
|
+
? this.resolveMedia(slide.media, path.posix.dirname(note.relativePath))
|
|
48
|
+
: undefined;
|
|
49
|
+
const withMedia = media ? { ...slide, media } : slide;
|
|
50
|
+
return this.applyNoteDisplay(withMedia, note, noteDisplay);
|
|
18
51
|
}
|
|
19
|
-
resolveSlide(slide) {
|
|
52
|
+
resolveSlide(slide, sourcePath, noteDisplay) {
|
|
20
53
|
let resolved = {};
|
|
21
|
-
let
|
|
54
|
+
let note;
|
|
22
55
|
if (slide.note) {
|
|
23
|
-
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
const fm = parsed.data;
|
|
27
|
-
const location = coerceLocation(fm.location, fm.zoom ?? fm.defaultZoom);
|
|
28
|
-
const media = coerceMedia(fm.cover ?? fm.image ?? fm.media);
|
|
29
|
-
resolved = {
|
|
30
|
-
title: typeof fm.title === 'string' ? fm.title : path.basename(notePath, '.md'),
|
|
31
|
-
...(typeof fm.description === 'string'
|
|
32
|
-
? { text: fm.description }
|
|
33
|
-
: typeof fm.summary === 'string'
|
|
34
|
-
? { text: fm.summary }
|
|
35
|
-
: {}),
|
|
36
|
-
...(location ? { location } : {}),
|
|
37
|
-
...(media ? { media } : {}),
|
|
38
|
-
...(typeof fm.mapmarker === 'string' ? { mapmarker: fm.mapmarker } : {}),
|
|
39
|
-
};
|
|
56
|
+
note = this.findIndexed(parseWikiLinkRef(slide.note));
|
|
57
|
+
if (note) {
|
|
58
|
+
resolved = slideFromNoteFrontmatter(note.frontmatter, path.basename(note.relativePath));
|
|
40
59
|
}
|
|
41
60
|
}
|
|
42
61
|
const merged = mergeResolvedSlide(slide, resolved);
|
|
43
|
-
const
|
|
44
|
-
?
|
|
45
|
-
:
|
|
46
|
-
|
|
62
|
+
const mediaBase = !slide.media && note
|
|
63
|
+
? path.posix.dirname(note.relativePath)
|
|
64
|
+
: this.vaultRelativeDirectory(sourcePath);
|
|
65
|
+
const media = merged.media ? this.resolveMedia(merged.media, mediaBase) : undefined;
|
|
66
|
+
const withMedia = { ...merged, ...(media ? { media } : {}) };
|
|
67
|
+
return note ? this.applyNoteDisplay(withMedia, note, noteDisplay) : withMedia;
|
|
68
|
+
}
|
|
69
|
+
applyNoteDisplay(slide, note, noteDisplay) {
|
|
70
|
+
if (noteDisplay === 'basic')
|
|
71
|
+
return slide;
|
|
72
|
+
if (noteDisplay === 'link') {
|
|
73
|
+
const href = this.options.resolveNoteHref?.(note.relativePath);
|
|
74
|
+
return href ? { ...slide, notePath: href } : slide;
|
|
75
|
+
}
|
|
76
|
+
const body = stripFrontmatter(readFileSync(note.absolutePath, 'utf8')).trim();
|
|
77
|
+
return body ? { ...slide, text: body } : slide;
|
|
47
78
|
}
|
|
48
|
-
resolveMedia(media,
|
|
79
|
+
resolveMedia(media, baseDirectory) {
|
|
49
80
|
if (/^(https?:|data:|blob:)/i.test(media.src) || !this.options.assetBase)
|
|
50
81
|
return media;
|
|
51
|
-
let source = parseWikiLinkRef(media.src);
|
|
52
|
-
if (source.startsWith('./')
|
|
53
|
-
|
|
82
|
+
let source = parseWikiLinkRef(media.src).replace(/\\/g, '/');
|
|
83
|
+
if (source.startsWith('./') || source.startsWith('../')) {
|
|
84
|
+
if (!baseDirectory)
|
|
85
|
+
return media;
|
|
86
|
+
source = path.posix.normalize(path.posix.join(baseDirectory, source));
|
|
87
|
+
if (source.startsWith('..'))
|
|
88
|
+
return media;
|
|
54
89
|
}
|
|
55
|
-
const url = `${this.options.assetBase.replace(/\/$/, '')}/${source.replace(/^\/+/, '')
|
|
90
|
+
const url = `${this.options.assetBase.replace(/\/$/, '')}/${source.replace(/^\/+/, '')}`;
|
|
56
91
|
return { ...media, src: url };
|
|
57
92
|
}
|
|
58
|
-
|
|
93
|
+
vaultRelativeDirectory(sourcePath) {
|
|
94
|
+
if (!sourcePath)
|
|
95
|
+
return undefined;
|
|
96
|
+
const relative = path.relative(this.options.vaultRoot, sourcePath).replace(/\\/g, '/');
|
|
97
|
+
if (!relative || relative.startsWith('..') || path.isAbsolute(relative))
|
|
98
|
+
return undefined;
|
|
99
|
+
return path.posix.dirname(relative);
|
|
100
|
+
}
|
|
101
|
+
findIndexed(ref) {
|
|
59
102
|
const normalized = ref.replace(/\\/g, '/').replace(/\.md$/i, '');
|
|
60
103
|
const exact = this.byRelativePath.get(normalized.toLowerCase());
|
|
61
104
|
if (exact)
|
|
62
|
-
return exact;
|
|
105
|
+
return this.notes.find((note) => note.absolutePath === exact);
|
|
63
106
|
const basename = path.posix.basename(normalized).toLowerCase();
|
|
64
107
|
const matches = this.byBasename.get(basename) ?? [];
|
|
65
108
|
if (matches.length > 1) {
|
|
66
109
|
throw new Error(`Ambiguous WikiLink '${ref}'. Use a Vault-relative path.`);
|
|
67
110
|
}
|
|
68
|
-
|
|
111
|
+
const match = matches[0];
|
|
112
|
+
return match ? this.notes.find((note) => note.absolutePath === match) : undefined;
|
|
69
113
|
}
|
|
70
114
|
scan(directory) {
|
|
71
115
|
if (!existsSync(directory))
|
|
72
116
|
return;
|
|
73
117
|
for (const entry of readdirSync(directory)) {
|
|
74
|
-
if (entry.startsWith('.'))
|
|
118
|
+
if (entry.startsWith('.') || EXCLUDED_DIRECTORIES.has(entry))
|
|
75
119
|
continue;
|
|
76
120
|
const full = path.join(directory, entry);
|
|
77
121
|
const stat = statSync(full);
|
|
@@ -81,12 +125,17 @@ export class VaultIndex {
|
|
|
81
125
|
}
|
|
82
126
|
if (!entry.toLowerCase().endsWith('.md'))
|
|
83
127
|
continue;
|
|
84
|
-
const relative = path
|
|
128
|
+
const relative = path
|
|
129
|
+
.relative(this.options.vaultRoot, full)
|
|
130
|
+
.replace(/\\/g, '/')
|
|
131
|
+
.replace(/\.md$/i, '');
|
|
85
132
|
const basename = path.basename(relative).toLowerCase();
|
|
86
133
|
const current = this.byBasename.get(basename) ?? [];
|
|
87
134
|
current.push(full);
|
|
88
135
|
this.byBasename.set(basename, current);
|
|
89
136
|
this.byRelativePath.set(relative.toLowerCase(), full);
|
|
137
|
+
const frontmatter = (matter(readFileSync(full, 'utf8')).data ?? {});
|
|
138
|
+
this.notes.push({ absolutePath: full, relativePath: relative, frontmatter });
|
|
90
139
|
}
|
|
91
140
|
}
|
|
92
141
|
}
|
package/dist/vault.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vault.js","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,cAAc,EACd,
|
|
1
|
+
{"version":3,"file":"vault.js","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@story-map/remark-story-map",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Remark transformer and browser client for publishing StoryMap blocks.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/kywk/story-map
|
|
8
|
+
"url": "git+https://github.com/kywk/story-map.git",
|
|
9
9
|
"directory": "packages/remark-story-map"
|
|
10
10
|
},
|
|
11
11
|
"publishConfig": {
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"dist"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@story-map/react-story-map": "0.1.
|
|
34
|
-
"@story-map/story-map-core": "0.1.
|
|
33
|
+
"@story-map/react-story-map": "0.1.1",
|
|
34
|
+
"@story-map/story-map-core": "0.1.1",
|
|
35
35
|
"gray-matter": "^4.0.3",
|
|
36
36
|
"unist-util-visit": "^5.1.0",
|
|
37
37
|
"leaflet": "^1.9.4"
|