@mrsf/marp-mrsf 0.4.8
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/LICENSE +21 -0
- package/README.md +142 -0
- package/dist/browser.d.ts +6 -0
- package/dist/browser.js +317 -0
- package/dist/browser.js.map +7 -0
- package/dist/controller.d.ts +173 -0
- package/dist/controller.js +1179 -0
- package/dist/controller.js.map +7 -0
- package/dist/gutter.d.ts +50 -0
- package/dist/html.d.ts +13 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +353 -0
- package/dist/index.js.map +7 -0
- package/dist/rules/core.d.ts +17 -0
- package/dist/rules/renderer.d.ts +10 -0
- package/dist/shared.d.ts +20 -0
- package/dist/style.css +522 -0
- package/dist/types.d.ts +105 -0
- package/package.json +85 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Wictor Wilén
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# @mrsf/marp-mrsf
|
|
2
|
+
|
|
3
|
+
Render Sidemark/MRSF review comments in Marpit and Marp HTML output.
|
|
4
|
+
|
|
5
|
+
This package installs into a Marpit-compatible renderer through `use()` and reuses the existing MRSF runtime model: line metadata on rendered content, a single serialized thread payload per deck, and browser-side interaction through the shared `MrsfController`.
|
|
6
|
+
|
|
7
|
+
This is the first public test release of the Marp integration. The package is ready for evaluation in Marpit and Marp hosts, but the vendor-only page anchoring path should still be treated as early feedback territory.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @mrsf/marp-mrsf
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
If you are starting from Marpit directly, install both packages:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @marp-team/marpit @mrsf/marp-mrsf
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
For Marp Core hosts:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @marp-team/marp-core @mrsf/marp-mrsf
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Browser and Bundler Support
|
|
28
|
+
|
|
29
|
+
The package exposes a browser-safe entry automatically through the standard `browser` export condition, so the same import works in Node.js, Vite, webpack, and esbuild.
|
|
30
|
+
|
|
31
|
+
In browser environments, use `comments` or `loader`. File-system-backed options such as `documentPath` and `sidecarPath` require Node.js.
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
### Inline sidecar data
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { Marpit } from "@marp-team/marpit";
|
|
39
|
+
import { mrsfPlugin } from "@mrsf/marp-mrsf";
|
|
40
|
+
import "@mrsf/marp-mrsf/style.css";
|
|
41
|
+
import { MrsfController } from "@mrsf/marp-mrsf/controller";
|
|
42
|
+
|
|
43
|
+
const marpit = new Marpit();
|
|
44
|
+
marpit.use(mrsfPlugin, {
|
|
45
|
+
comments: sidecarData,
|
|
46
|
+
interactive: true,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const { html } = marpit.render(markdownSource);
|
|
50
|
+
|
|
51
|
+
const container = document.querySelector(".marpit");
|
|
52
|
+
if (container) {
|
|
53
|
+
new MrsfController(container, { interactive: true });
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Load from disk in Node.js
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
const marpit = new Marpit();
|
|
61
|
+
marpit.use(mrsfPlugin, {
|
|
62
|
+
documentPath: "slides/deck.md",
|
|
63
|
+
interactive: true,
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The plugin will look for `slides/deck.md.review.yaml` or `slides/deck.md.review.json` next to the Markdown document.
|
|
68
|
+
|
|
69
|
+
### Custom loader
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
marpit.use(mrsfPlugin, {
|
|
73
|
+
loader: () => currentSidecarState,
|
|
74
|
+
interactive: true,
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Marp Core
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { Marp } from "@marp-team/marp-core";
|
|
82
|
+
import { mrsfPlugin } from "@mrsf/marp-mrsf";
|
|
83
|
+
import "@mrsf/marp-mrsf/style.css";
|
|
84
|
+
|
|
85
|
+
const marp = new Marp({ inlineSVG: true });
|
|
86
|
+
marp.use(mrsfPlugin, {
|
|
87
|
+
comments: sidecarData,
|
|
88
|
+
interactive: true,
|
|
89
|
+
lineHighlight: true,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const { html, css } = marp.render(markdownSource);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Styles and Runtime
|
|
96
|
+
|
|
97
|
+
Include the default stylesheet to get shared badges, highlights, gutters, and tooltips:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import "@mrsf/marp-mrsf/style.css";
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
For interactive hosts, mount the shared controller after the rendered HTML is in the DOM:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import { MrsfController } from "@mrsf/marp-mrsf/controller";
|
|
107
|
+
|
|
108
|
+
new MrsfController(container, {
|
|
109
|
+
interactive: true,
|
|
110
|
+
inlineHighlights: true,
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
When users interact with comments, the controller dispatches the same `mrsf:*` events used by the other rendering plugins. The host remains responsible for persistence.
|
|
115
|
+
|
|
116
|
+
## Vendor Page Hints
|
|
117
|
+
|
|
118
|
+
The Marp integration supports vendor-only `x_page` hints on comments. This is useful when a presentation-level note belongs to a whole rendered page rather than a specific source line.
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
comments:
|
|
122
|
+
- id: page-2-note
|
|
123
|
+
author: Review Bot
|
|
124
|
+
timestamp: "2026-03-25T12:10:00Z"
|
|
125
|
+
text: Tighten the slide title and reduce the bullet count.
|
|
126
|
+
resolved: false
|
|
127
|
+
x_page: 2
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`x_page` is not part of the MRSF standard. It is preserved as vendor metadata and interpreted by the Marp renderer only.
|
|
131
|
+
|
|
132
|
+
## Notes
|
|
133
|
+
|
|
134
|
+
1. The host application owns persistence. Listen for `mrsf:*` events and save sidecar changes yourself.
|
|
135
|
+
2. The plugin adds `data-mrsf-page` to rendered page containers for runtime navigation.
|
|
136
|
+
3. Vendor hints such as `x_page` can be used to attach a comment to a rendered page when line-level anchoring is not the right fit.
|
|
137
|
+
4. The plugin does not propose any MRSF spec changes. Page metadata is a renderer concern, not a canonical sidecar field.
|
|
138
|
+
5. Inline SVG mode is supported and tags the SVG page containers with `data-mrsf-page`.
|
|
139
|
+
|
|
140
|
+
## Demo
|
|
141
|
+
|
|
142
|
+
An interactive demo lives in [`examples/marp-demo`](../../examples/marp-demo). It renders a small deck, keeps the sidecar in local host state, supports add/reply/edit/resolve/delete flows, and includes both line-based and `x_page`-based comments.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MrsfMarpPlugin } from "./shared.js";
|
|
2
|
+
export type { MrsfPluginOptions, SlimComment, CommentThread, LineMap, CommentLoader } from "./types.js";
|
|
3
|
+
export type { MrsfMarpPlugin, MarpitLike, MarpitPluginContext } from "./shared.js";
|
|
4
|
+
export declare const mrsfPlugin: MrsfMarpPlugin;
|
|
5
|
+
export default mrsfPlugin;
|
|
6
|
+
//# sourceMappingURL=browser.d.ts.map
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
// ../shared/dist/comments.js
|
|
2
|
+
function toSlimComments(doc) {
|
|
3
|
+
return doc.comments.map((c) => ({
|
|
4
|
+
id: c.id,
|
|
5
|
+
author: c.author || "Unknown",
|
|
6
|
+
text: c.text || "",
|
|
7
|
+
line: c.line ?? null,
|
|
8
|
+
x_page: typeof c.x_page === "number" ? c.x_page : null,
|
|
9
|
+
end_line: c.end_line ?? null,
|
|
10
|
+
start_column: c.start_column ?? null,
|
|
11
|
+
end_column: c.end_column ?? null,
|
|
12
|
+
selected_text: c.selected_text || null,
|
|
13
|
+
resolved: !!c.resolved,
|
|
14
|
+
reply_to: c.reply_to || null,
|
|
15
|
+
severity: c.severity || null,
|
|
16
|
+
type: c.type || null,
|
|
17
|
+
timestamp: c.timestamp || null
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
function groupByLine(comments) {
|
|
21
|
+
const rootComments = comments.filter((c) => !c.reply_to && c.line != null);
|
|
22
|
+
const replies = comments.filter((c) => c.reply_to);
|
|
23
|
+
const replyMap = /* @__PURE__ */ new Map();
|
|
24
|
+
for (const r of replies) {
|
|
25
|
+
const list = replyMap.get(r.reply_to) || [];
|
|
26
|
+
list.push(r);
|
|
27
|
+
replyMap.set(r.reply_to, list);
|
|
28
|
+
}
|
|
29
|
+
const lineMap = /* @__PURE__ */ new Map();
|
|
30
|
+
for (const c of rootComments) {
|
|
31
|
+
const line = c.line;
|
|
32
|
+
const threads = lineMap.get(line) || [];
|
|
33
|
+
threads.push({
|
|
34
|
+
comment: c,
|
|
35
|
+
replies: replyMap.get(c.id) || []
|
|
36
|
+
});
|
|
37
|
+
lineMap.set(line, threads);
|
|
38
|
+
}
|
|
39
|
+
return lineMap;
|
|
40
|
+
}
|
|
41
|
+
function resolveComments(loader, options, env) {
|
|
42
|
+
const showResolved = options.showResolved ?? true;
|
|
43
|
+
const doc = loader(options, env);
|
|
44
|
+
if (!doc || !doc.comments || doc.comments.length === 0) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
let comments = toSlimComments(doc);
|
|
48
|
+
if (!showResolved) {
|
|
49
|
+
comments = comments.filter((c) => !c.resolved);
|
|
50
|
+
}
|
|
51
|
+
if (comments.length === 0)
|
|
52
|
+
return null;
|
|
53
|
+
const lineMap = groupByLine(comments);
|
|
54
|
+
return { lineMap, comments };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/rules/core.ts
|
|
58
|
+
function buildPageLineMap(tokens) {
|
|
59
|
+
const pageLineMap = /* @__PURE__ */ new Map();
|
|
60
|
+
let pageNumber = 0;
|
|
61
|
+
for (const token of tokens) {
|
|
62
|
+
if (token.type !== "marpit_slide_open" || !token.map) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
pageNumber += 1;
|
|
66
|
+
pageLineMap.set(pageNumber, token.map[0] + 1);
|
|
67
|
+
}
|
|
68
|
+
return pageLineMap;
|
|
69
|
+
}
|
|
70
|
+
function mergePageScopedThreads(lineMap, comments, pageLineMap) {
|
|
71
|
+
const merged = new Map(
|
|
72
|
+
Array.from(lineMap.entries(), ([line, threads]) => [
|
|
73
|
+
line,
|
|
74
|
+
threads.map((thread) => ({
|
|
75
|
+
comment: thread.comment,
|
|
76
|
+
replies: [...thread.replies]
|
|
77
|
+
}))
|
|
78
|
+
])
|
|
79
|
+
);
|
|
80
|
+
const replyMap = /* @__PURE__ */ new Map();
|
|
81
|
+
for (const comment of comments) {
|
|
82
|
+
if (!comment.reply_to) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const replies = replyMap.get(comment.reply_to) || [];
|
|
86
|
+
replies.push(comment);
|
|
87
|
+
replyMap.set(comment.reply_to, replies);
|
|
88
|
+
}
|
|
89
|
+
for (const comment of comments) {
|
|
90
|
+
if (comment.reply_to || comment.line != null || comment.x_page == null) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const displayLine = pageLineMap.get(comment.x_page);
|
|
94
|
+
if (displayLine == null) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const threadComment = {
|
|
98
|
+
...comment,
|
|
99
|
+
line: displayLine
|
|
100
|
+
};
|
|
101
|
+
const threadReplies = (replyMap.get(comment.id) || []).map((reply) => ({
|
|
102
|
+
...reply,
|
|
103
|
+
line: reply.line ?? displayLine
|
|
104
|
+
}));
|
|
105
|
+
const threads = merged.get(displayLine) || [];
|
|
106
|
+
threads.push({
|
|
107
|
+
comment: threadComment,
|
|
108
|
+
replies: threadReplies
|
|
109
|
+
});
|
|
110
|
+
merged.set(displayLine, threads);
|
|
111
|
+
}
|
|
112
|
+
return merged;
|
|
113
|
+
}
|
|
114
|
+
function installCoreRule(md, resolveComments2, options = {}) {
|
|
115
|
+
md.core.ruler.push("mrsf_inject", (state) => {
|
|
116
|
+
const result = resolveComments2(state);
|
|
117
|
+
if (!result) return;
|
|
118
|
+
const pageLineMap = buildPageLineMap(state.tokens);
|
|
119
|
+
const lineMap = mergePageScopedThreads(result.lineMap, result.comments, pageLineMap);
|
|
120
|
+
const tokens = state.tokens;
|
|
121
|
+
const TokenCtor = state.Token;
|
|
122
|
+
const processed = /* @__PURE__ */ new Set();
|
|
123
|
+
for (let i = tokens.length - 1; i >= 0; i--) {
|
|
124
|
+
const token = tokens[i];
|
|
125
|
+
const map = token.map;
|
|
126
|
+
if (!map) continue;
|
|
127
|
+
if (token.type === "inline") continue;
|
|
128
|
+
const startLine1 = map[0] + 1;
|
|
129
|
+
const endLine1 = map[1];
|
|
130
|
+
token.attrSet("data-mrsf-line", String(startLine1));
|
|
131
|
+
token.attrSet("data-mrsf-start-line", String(startLine1));
|
|
132
|
+
token.attrSet("data-mrsf-end-line", String(endLine1));
|
|
133
|
+
for (let line0 = map[0]; line0 < map[1]; line0++) {
|
|
134
|
+
const line = line0 + 1;
|
|
135
|
+
if (processed.has(line)) continue;
|
|
136
|
+
processed.add(line);
|
|
137
|
+
const threads = lineMap.get(line);
|
|
138
|
+
if (threads && threads.length > 0) {
|
|
139
|
+
if (options.lineHighlight) {
|
|
140
|
+
const existingClass = token.attrGet("class") || "";
|
|
141
|
+
if (!existingClass.includes("mrsf-line-highlight")) {
|
|
142
|
+
token.attrSet(
|
|
143
|
+
"class",
|
|
144
|
+
existingClass ? `${existingClass} mrsf-line-highlight` : "mrsf-line-highlight"
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
token.attrSet("data-mrsf-line", String(line));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const allThreads = [];
|
|
153
|
+
for (const threads of lineMap.values()) {
|
|
154
|
+
allThreads.push(...threads);
|
|
155
|
+
}
|
|
156
|
+
if (allThreads.length > 0) {
|
|
157
|
+
const scriptToken = new TokenCtor("mrsf_data_script", "", 0);
|
|
158
|
+
scriptToken.meta = { threads: allThreads };
|
|
159
|
+
tokens.push(scriptToken);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/rules/renderer.ts
|
|
165
|
+
function escapeAttribute(value) {
|
|
166
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
167
|
+
}
|
|
168
|
+
function installRendererRules(md, options = {}) {
|
|
169
|
+
md.renderer.rules["mrsf_data_script"] = (tokens, idx) => {
|
|
170
|
+
const { threads } = tokens[idx].meta;
|
|
171
|
+
const payload = JSON.stringify({ threads });
|
|
172
|
+
if (options.dataContainer === "element") {
|
|
173
|
+
const elementId = options.dataElementId || "mrsf-comment-data";
|
|
174
|
+
return `<div id="${escapeAttribute(elementId)}" data-mrsf-json="${escapeAttribute(payload)}" aria-hidden="true"></div>`;
|
|
175
|
+
}
|
|
176
|
+
const data = payload.replace(/</g, "\\u003c");
|
|
177
|
+
return `<script type="application/mrsf+json">${data}</script>`;
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// src/shared.ts
|
|
182
|
+
var patchedRenderers = /* @__PURE__ */ new WeakSet();
|
|
183
|
+
function installMarkdownMrsfPlugin(md, options, loader) {
|
|
184
|
+
installCoreRule(
|
|
185
|
+
md,
|
|
186
|
+
(state) => resolveComments(loader, options, state.env),
|
|
187
|
+
{ lineHighlight: options.lineHighlight ?? false }
|
|
188
|
+
);
|
|
189
|
+
installRendererRules(md, {
|
|
190
|
+
dataContainer: options.dataContainer,
|
|
191
|
+
dataElementId: options.dataElementId
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
function createMarpPlugin(loader) {
|
|
195
|
+
return function mrsfPlugin2(context, options = {}) {
|
|
196
|
+
const markdown = context.markdown ?? context.marpit?.markdown;
|
|
197
|
+
if (markdown) {
|
|
198
|
+
installMarkdownMrsfPlugin(markdown, options, loader);
|
|
199
|
+
}
|
|
200
|
+
if (!context.marpit) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
patchRender(context.marpit, options);
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function patchRender(marpit, options) {
|
|
207
|
+
if (patchedRenderers.has(marpit)) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const originalRender = marpit.render.bind(marpit);
|
|
211
|
+
marpit.render = (markdown, env) => {
|
|
212
|
+
const result = originalRender(markdown, env);
|
|
213
|
+
const fallbackHtml = Array.isArray(result.html) ? originalRender(markdown, { ...env ?? {}, htmlAsArray: false }).html : null;
|
|
214
|
+
return {
|
|
215
|
+
...result,
|
|
216
|
+
html: normalizeRenderedHtml(result.html, options, typeof fallbackHtml === "string" ? fallbackHtml : null)
|
|
217
|
+
};
|
|
218
|
+
};
|
|
219
|
+
patchedRenderers.add(marpit);
|
|
220
|
+
}
|
|
221
|
+
var SCRIPT_RE = /<script type="application\/mrsf\+json">[\s\S]*?<\/script>/g;
|
|
222
|
+
function normalizeRenderedHtml(html, options, fallbackHtml = null) {
|
|
223
|
+
if (Array.isArray(html)) {
|
|
224
|
+
let payload2 = null;
|
|
225
|
+
const pages = html.map((pageHtml, index) => {
|
|
226
|
+
const extracted2 = extractPayloads(pageHtml);
|
|
227
|
+
if (extracted2.payloads.length > 0) {
|
|
228
|
+
payload2 = extracted2.payloads[extracted2.payloads.length - 1];
|
|
229
|
+
}
|
|
230
|
+
return annotatePageFragment(extracted2.html, index + 1, options);
|
|
231
|
+
});
|
|
232
|
+
if (!payload2 && fallbackHtml) {
|
|
233
|
+
const fallback = extractPayloads(fallbackHtml);
|
|
234
|
+
payload2 = fallback.payloads[fallback.payloads.length - 1] ?? null;
|
|
235
|
+
}
|
|
236
|
+
if (payload2 && pages.length > 0) {
|
|
237
|
+
pages[pages.length - 1] += payload2;
|
|
238
|
+
}
|
|
239
|
+
return pages;
|
|
240
|
+
}
|
|
241
|
+
const extracted = extractPayloads(html);
|
|
242
|
+
const annotated = annotateSectionTags(extracted.html, options);
|
|
243
|
+
if (extracted.payloads.length === 0) {
|
|
244
|
+
return annotated;
|
|
245
|
+
}
|
|
246
|
+
const payload = extracted.payloads[extracted.payloads.length - 1];
|
|
247
|
+
return insertPayloadIntoContainer(annotated, payload);
|
|
248
|
+
}
|
|
249
|
+
function extractPayloads(html) {
|
|
250
|
+
const payloads = html.match(SCRIPT_RE) ?? [];
|
|
251
|
+
return {
|
|
252
|
+
html: html.replace(SCRIPT_RE, ""),
|
|
253
|
+
payloads
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function annotatePageFragment(html, pageNumber, options) {
|
|
257
|
+
const attrName = resolvePageAttributeName(options);
|
|
258
|
+
return html.replace(/<([a-zA-Z][\w:-]*)(\s|>)/, `<$1 ${attrName}="${pageNumber}"$2`);
|
|
259
|
+
}
|
|
260
|
+
function annotateSectionTags(html, options) {
|
|
261
|
+
if (html.includes("<svg") && html.includes("data-marpit-svg")) {
|
|
262
|
+
return annotateSvgPageTags(html, options);
|
|
263
|
+
}
|
|
264
|
+
const attrName = resolvePageAttributeName(options);
|
|
265
|
+
let pageNumber = 0;
|
|
266
|
+
return html.replace(/<section(\s|>)/g, (_match, suffix) => {
|
|
267
|
+
pageNumber += 1;
|
|
268
|
+
return `<section ${attrName}="${pageNumber}"${suffix}`;
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
function annotateSvgPageTags(html, options) {
|
|
272
|
+
const attrName = resolvePageAttributeName(options);
|
|
273
|
+
let pageNumber = 0;
|
|
274
|
+
return html.replace(/<svg\b([^>]*)>/g, (_match, attrs) => {
|
|
275
|
+
if (!attrs.includes("data-marpit-svg")) {
|
|
276
|
+
return `<svg${attrs}>`;
|
|
277
|
+
}
|
|
278
|
+
pageNumber += 1;
|
|
279
|
+
return `<svg${attrs} ${attrName}="${pageNumber}">`;
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
function resolvePageAttributeName(_options) {
|
|
283
|
+
return "data-mrsf-page";
|
|
284
|
+
}
|
|
285
|
+
function insertPayloadIntoContainer(html, payload) {
|
|
286
|
+
const closingTagIndex = html.lastIndexOf("</");
|
|
287
|
+
if (closingTagIndex === -1) {
|
|
288
|
+
return html + payload;
|
|
289
|
+
}
|
|
290
|
+
return html.slice(0, closingTagIndex) + payload + html.slice(closingTagIndex);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// src/browser.ts
|
|
294
|
+
var mrsfPlugin = createMarpPlugin((options, env) => {
|
|
295
|
+
if (options.comments) {
|
|
296
|
+
return options.comments;
|
|
297
|
+
}
|
|
298
|
+
if (options.loader) {
|
|
299
|
+
try {
|
|
300
|
+
return options.loader(options, env);
|
|
301
|
+
} catch {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (options.sidecarPath || options.documentPath) {
|
|
306
|
+
console.warn(
|
|
307
|
+
"[@mrsf/marp-mrsf] sidecarPath and documentPath require Node.js. Use `comments` or `loader` options in browser environments."
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
return null;
|
|
311
|
+
});
|
|
312
|
+
var browser_default = mrsfPlugin;
|
|
313
|
+
export {
|
|
314
|
+
browser_default as default,
|
|
315
|
+
mrsfPlugin
|
|
316
|
+
};
|
|
317
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../shared/src/comments.ts", "../src/rules/core.ts", "../src/rules/renderer.ts", "../src/shared.ts", "../src/browser.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Shared comment loading and grouping logic for MRSF rendering plugins.\n */\n\nimport type { MrsfDocument } from \"@mrsf/cli\";\nimport type { MrsfPluginOptions, SlimComment, CommentThread, LineMap, CommentLoader } from \"./types.js\";\n\nexport type { CommentLoader };\n\n/**\n * Convert an MrsfDocument into a slim comment array.\n */\nexport function toSlimComments(doc: MrsfDocument): SlimComment[] {\n return doc.comments.map((c) => ({\n id: c.id,\n author: c.author || \"Unknown\",\n text: c.text || \"\",\n line: c.line ?? null,\n x_page: typeof c.x_page === \"number\" ? c.x_page : null,\n end_line: c.end_line ?? null,\n start_column: c.start_column ?? null,\n end_column: c.end_column ?? null,\n selected_text: c.selected_text || null,\n resolved: !!c.resolved,\n reply_to: c.reply_to || null,\n severity: c.severity || null,\n type: c.type || null,\n timestamp: c.timestamp || null,\n }));\n}\n\n/**\n * Group comments by line number, threading replies under parents.\n */\nexport function groupByLine(comments: SlimComment[]): LineMap {\n const rootComments = comments.filter((c) => !c.reply_to && c.line != null);\n const replies = comments.filter((c) => c.reply_to);\n\n const replyMap = new Map<string, SlimComment[]>();\n for (const r of replies) {\n const list = replyMap.get(r.reply_to!) || [];\n list.push(r);\n replyMap.set(r.reply_to!, list);\n }\n\n const lineMap: LineMap = new Map();\n for (const c of rootComments) {\n const line = c.line!;\n const threads = lineMap.get(line) || [];\n threads.push({\n comment: c,\n replies: replyMap.get(c.id) || [],\n });\n lineMap.set(line, threads);\n }\n\n return lineMap;\n}\n\n/**\n * Resolve options into a filtered LineMap ready for rendering.\n * Returns null if there are no comments to render.\n */\nexport function resolveComments(\n loader: CommentLoader,\n options: MrsfPluginOptions,\n env?: unknown,\n): { lineMap: LineMap; comments: SlimComment[] } | null {\n const showResolved = options.showResolved ?? true;\n\n const doc = loader(options, env);\n if (!doc || !doc.comments || doc.comments.length === 0) {\n return null;\n }\n\n let comments = toSlimComments(doc);\n if (!showResolved) {\n comments = comments.filter((c) => !c.resolved);\n }\n\n if (comments.length === 0) return null;\n\n const lineMap = groupByLine(comments);\n return { lineMap, comments };\n}\n", "import type Token from \"markdown-it/lib/token.mjs\";\nimport type StateCore from \"markdown-it/lib/rules_core/state_core.mjs\";\nimport type { LineMap, CommentThread, SlimComment } from \"../types.js\";\n\nexport interface CoreRuleOptions {\n lineHighlight?: boolean;\n}\n\nexport interface ResolvedCommentData {\n lineMap: LineMap;\n comments: SlimComment[];\n}\n\nfunction buildPageLineMap(tokens: Token[]): Map<number, number> {\n const pageLineMap = new Map<number, number>();\n let pageNumber = 0;\n\n for (const token of tokens) {\n if (token.type !== \"marpit_slide_open\" || !token.map) {\n continue;\n }\n\n pageNumber += 1;\n pageLineMap.set(pageNumber, token.map[0] + 1);\n }\n\n return pageLineMap;\n}\n\nfunction mergePageScopedThreads(\n lineMap: LineMap,\n comments: SlimComment[],\n pageLineMap: Map<number, number>,\n): LineMap {\n const merged: LineMap = new Map(\n Array.from(lineMap.entries(), ([line, threads]) => [\n line,\n threads.map((thread) => ({\n comment: thread.comment,\n replies: [...thread.replies],\n })),\n ]),\n );\n const replyMap = new Map<string, SlimComment[]>();\n\n for (const comment of comments) {\n if (!comment.reply_to) {\n continue;\n }\n\n const replies = replyMap.get(comment.reply_to) || [];\n replies.push(comment);\n replyMap.set(comment.reply_to, replies);\n }\n\n for (const comment of comments) {\n if (comment.reply_to || comment.line != null || comment.x_page == null) {\n continue;\n }\n\n const displayLine = pageLineMap.get(comment.x_page);\n if (displayLine == null) {\n continue;\n }\n\n const threadComment: SlimComment = {\n ...comment,\n line: displayLine,\n };\n const threadReplies = (replyMap.get(comment.id) || []).map((reply) => ({\n ...reply,\n line: reply.line ?? displayLine,\n }));\n const threads = merged.get(displayLine) || [];\n\n threads.push({\n comment: threadComment,\n replies: threadReplies,\n });\n merged.set(displayLine, threads);\n }\n\n return merged;\n}\n\nexport function installCoreRule(\n md: { core: { ruler: { push: (name: string, fn: (state: StateCore) => void) => void } } },\n resolveComments: (state: StateCore) => ResolvedCommentData | null,\n options: CoreRuleOptions = {},\n): void {\n md.core.ruler.push(\"mrsf_inject\", (state: StateCore) => {\n const result = resolveComments(state);\n if (!result) return;\n\n const pageLineMap = buildPageLineMap(state.tokens);\n const lineMap = mergePageScopedThreads(result.lineMap, result.comments, pageLineMap);\n const tokens = state.tokens;\n const TokenCtor = state.Token;\n const processed = new Set<number>();\n\n for (let i = tokens.length - 1; i >= 0; i--) {\n const token = tokens[i];\n const map = token.map;\n if (!map) continue;\n\n if (token.type === \"inline\") continue;\n\n const startLine1 = map[0] + 1;\n const endLine1 = map[1];\n token.attrSet(\"data-mrsf-line\", String(startLine1));\n token.attrSet(\"data-mrsf-start-line\", String(startLine1));\n token.attrSet(\"data-mrsf-end-line\", String(endLine1));\n\n for (let line0 = map[0]; line0 < map[1]; line0++) {\n const line = line0 + 1;\n if (processed.has(line)) continue;\n processed.add(line);\n\n const threads = lineMap.get(line);\n if (threads && threads.length > 0) {\n if (options.lineHighlight) {\n const existingClass = token.attrGet(\"class\") || \"\";\n if (!existingClass.includes(\"mrsf-line-highlight\")) {\n token.attrSet(\n \"class\",\n existingClass ? `${existingClass} mrsf-line-highlight` : \"mrsf-line-highlight\",\n );\n }\n }\n token.attrSet(\"data-mrsf-line\", String(line));\n }\n }\n }\n\n const allThreads: CommentThread[] = [];\n for (const threads of lineMap.values()) {\n allThreads.push(...threads);\n }\n if (allThreads.length > 0) {\n const scriptToken = new TokenCtor(\"mrsf_data_script\", \"\", 0);\n scriptToken.meta = { threads: allThreads };\n tokens.push(scriptToken);\n }\n });\n}", "import type { CommentThread } from \"../types.js\";\n\nexport interface RendererRuleOptions {\n dataContainer?: \"script\" | \"element\";\n dataElementId?: string;\n}\n\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n}\n\nexport function installRendererRules(\n md: { renderer: { rules: Record<string, ((...args: any[]) => string) | undefined> } },\n options: RendererRuleOptions = {},\n): void {\n md.renderer.rules[\"mrsf_data_script\"] = (\n tokens: { meta: { threads: CommentThread[] } }[],\n idx: number,\n ): string => {\n const { threads } = tokens[idx].meta;\n const payload = JSON.stringify({ threads });\n if (options.dataContainer === \"element\") {\n const elementId = options.dataElementId || \"mrsf-comment-data\";\n return `<div id=\"${escapeAttribute(elementId)}\" data-mrsf-json=\"${escapeAttribute(payload)}\" aria-hidden=\"true\"></div>`;\n }\n\n const data = payload.replace(/</g, \"\\\\u003c\");\n return `<script type=\"application/mrsf+json\">${data}</script>`;\n };\n}", "import type MarkdownIt from \"markdown-it\";\nimport { resolveComments } from \"@mrsf/plugin-shared\";\nimport type { CommentLoader, MrsfPluginOptions } from \"./types.js\";\nimport { installCoreRule } from \"./rules/core.js\";\nimport { installRendererRules } from \"./rules/renderer.js\";\n\nexport interface MarpitRenderResult {\n html: string | string[];\n css: string;\n comments?: string[][];\n}\n\nexport interface MarpitLike {\n render(markdown: string, env?: Record<string, unknown>): MarpitRenderResult;\n use(plugin: (context: unknown, ...params: unknown[]) => unknown, ...params: unknown[]): unknown;\n markdown?: MarkdownIt;\n}\n\nexport interface MarpitPluginContext {\n marpit?: MarpitLike;\n markdown?: MarkdownIt;\n}\n\nexport type MrsfMarpPlugin = (\n context: MarpitPluginContext,\n options?: MrsfPluginOptions,\n) => void;\n\nconst patchedRenderers = new WeakSet<MarpitLike>();\n\nexport function installMarkdownMrsfPlugin(\n md: MarkdownIt,\n options: MrsfPluginOptions,\n loader: CommentLoader,\n): void {\n installCoreRule(\n md,\n (state) => resolveComments(loader, options, state.env),\n { lineHighlight: options.lineHighlight ?? false },\n );\n installRendererRules(md, {\n dataContainer: options.dataContainer,\n dataElementId: options.dataElementId,\n });\n}\n\nexport function createMarpPlugin(loader: CommentLoader): MrsfMarpPlugin {\n return function mrsfPlugin(\n context: MarpitPluginContext,\n options: MrsfPluginOptions = {},\n ): void {\n const markdown = context.markdown ?? context.marpit?.markdown;\n if (markdown) {\n installMarkdownMrsfPlugin(markdown, options, loader);\n }\n\n if (!context.marpit) {\n return;\n }\n\n patchRender(context.marpit, options);\n };\n}\n\nfunction patchRender(marpit: MarpitLike, options: MrsfPluginOptions): void {\n if (patchedRenderers.has(marpit)) {\n return;\n }\n\n const originalRender = marpit.render.bind(marpit);\n marpit.render = (markdown: string, env?: Record<string, unknown>): MarpitRenderResult => {\n const result = originalRender(markdown, env);\n const fallbackHtml = Array.isArray(result.html)\n ? originalRender(markdown, { ...(env ?? {}), htmlAsArray: false }).html\n : null;\n\n return {\n ...result,\n html: normalizeRenderedHtml(result.html, options, typeof fallbackHtml === \"string\" ? fallbackHtml : null),\n };\n };\n\n patchedRenderers.add(marpit);\n}\n\nconst SCRIPT_RE = /<script type=\"application\\/mrsf\\+json\">[\\s\\S]*?<\\/script>/g;\n\nfunction normalizeRenderedHtml(\n html: string | string[],\n options: MrsfPluginOptions,\n fallbackHtml: string | null = null,\n): string | string[] {\n if (Array.isArray(html)) {\n let payload: string | null = null;\n\n const pages = html.map((pageHtml, index) => {\n const extracted = extractPayloads(pageHtml);\n if (extracted.payloads.length > 0) {\n payload = extracted.payloads[extracted.payloads.length - 1];\n }\n\n return annotatePageFragment(extracted.html, index + 1, options);\n });\n\n if (!payload && fallbackHtml) {\n const fallback = extractPayloads(fallbackHtml);\n payload = fallback.payloads[fallback.payloads.length - 1] ?? null;\n }\n\n if (payload && pages.length > 0) {\n pages[pages.length - 1] += payload;\n }\n\n return pages;\n }\n\n const extracted = extractPayloads(html);\n const annotated = annotateSectionTags(extracted.html, options);\n\n if (extracted.payloads.length === 0) {\n return annotated;\n }\n\n const payload = extracted.payloads[extracted.payloads.length - 1];\n return insertPayloadIntoContainer(annotated, payload);\n}\n\nfunction extractPayloads(html: string): { html: string; payloads: string[] } {\n const payloads = html.match(SCRIPT_RE) ?? [];\n return {\n html: html.replace(SCRIPT_RE, \"\"),\n payloads,\n };\n}\n\nfunction annotatePageFragment(\n html: string,\n pageNumber: number,\n options: MrsfPluginOptions,\n): string {\n const attrName = resolvePageAttributeName(options);\n return html.replace(/<([a-zA-Z][\\w:-]*)(\\s|>)/, `<$1 ${attrName}=\"${pageNumber}\"$2`);\n}\n\nfunction annotateSectionTags(html: string, options: MrsfPluginOptions): string {\n if (html.includes(\"<svg\") && html.includes(\"data-marpit-svg\")) {\n return annotateSvgPageTags(html, options);\n }\n\n const attrName = resolvePageAttributeName(options);\n let pageNumber = 0;\n\n return html.replace(/<section(\\s|>)/g, (_match, suffix: string) => {\n pageNumber += 1;\n return `<section ${attrName}=\"${pageNumber}\"${suffix}`;\n });\n}\n\nfunction annotateSvgPageTags(html: string, options: MrsfPluginOptions): string {\n const attrName = resolvePageAttributeName(options);\n let pageNumber = 0;\n\n return html.replace(/<svg\\b([^>]*)>/g, (_match, attrs: string) => {\n if (!attrs.includes(\"data-marpit-svg\")) {\n return `<svg${attrs}>`;\n }\n\n pageNumber += 1;\n return `<svg${attrs} ${attrName}=\"${pageNumber}\">`;\n });\n}\n\nfunction resolvePageAttributeName(_options: MrsfPluginOptions): string {\n return \"data-mrsf-page\";\n}\n\nfunction insertPayloadIntoContainer(html: string, payload: string): string {\n const closingTagIndex = html.lastIndexOf(\"</\");\n if (closingTagIndex === -1) {\n return html + payload;\n }\n\n return html.slice(0, closingTagIndex) + payload + html.slice(closingTagIndex);\n}", "import type { MrsfPluginOptions } from \"./types.js\";\nimport { createMarpPlugin } from \"./shared.js\";\nimport type { MrsfMarpPlugin } from \"./shared.js\";\n\nexport type { MrsfPluginOptions, SlimComment, CommentThread, LineMap, CommentLoader } from \"./types.js\";\nexport type { MrsfMarpPlugin, MarpitLike, MarpitPluginContext } from \"./shared.js\";\n\nexport const mrsfPlugin: MrsfMarpPlugin = createMarpPlugin((options: MrsfPluginOptions, env?: unknown) => {\n if (options.comments) {\n return options.comments;\n }\n\n if (options.loader) {\n try {\n return options.loader(options, env);\n } catch {\n return null;\n }\n }\n\n if (options.sidecarPath || options.documentPath) {\n console.warn(\n \"[@mrsf/marp-mrsf] sidecarPath and documentPath require Node.js. \" +\n \"Use `comments` or `loader` options in browser environments.\",\n );\n }\n\n return null;\n});\n\nexport default mrsfPlugin;"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["resolveComments", "mrsfPlugin", "payload", "extracted"]
|
|
7
|
+
}
|