confluence-md-sync 0.11.0 → 0.11.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/dist/markdown/render.d.ts +6 -0
- package/dist/markdown/render.js +30 -12
- package/package.json +1 -1
|
@@ -55,6 +55,12 @@ export interface RenderStorageOptions {
|
|
|
55
55
|
title: string;
|
|
56
56
|
space?: string;
|
|
57
57
|
} | null;
|
|
58
|
+
/** Local Markdown assets: attachment on this page, or a canonical repository URL. */
|
|
59
|
+
resourceResolver?: (href: string) => {
|
|
60
|
+
attachment: string;
|
|
61
|
+
} | {
|
|
62
|
+
url: string;
|
|
63
|
+
} | null;
|
|
58
64
|
}
|
|
59
65
|
export declare class MissingAttachmentUrlError extends Error {
|
|
60
66
|
constructor(message: string);
|
package/dist/markdown/render.js
CHANGED
|
@@ -120,22 +120,40 @@ export function renderToStorage(markdown, urls, opts = {}) {
|
|
|
120
120
|
// манифеста). Только markdown-ссылки (`<a href>` из markdown-it); плейсхолдеры
|
|
121
121
|
// {{file:}}/{{img:}} рендерятся ниже и сюда ещё не попали. Внешние URL/якоря
|
|
122
122
|
// резолвер отсекает (возвращает null) — они остаются как есть.
|
|
123
|
-
if (opts.
|
|
124
|
-
|
|
125
|
-
html = html.replace(/<a href="([^"]*)">([\s\S]*?)<\/a>/g, (full, href, inner) => {
|
|
123
|
+
if (opts.resourceResolver) {
|
|
124
|
+
html = html.replace(/<img\b[^>]*\bsrc="([^"]*)"[^>]*\/?>/g, (full, href) => {
|
|
126
125
|
const decoded = unescapeHtml(href);
|
|
127
126
|
if (/^(?:[a-z][a-z0-9+.-]*:|#|\/\/)/i.test(decoded))
|
|
128
|
-
return full;
|
|
129
|
-
const target =
|
|
127
|
+
return full;
|
|
128
|
+
const target = opts.resourceResolver(decoded);
|
|
130
129
|
if (!target)
|
|
131
130
|
return full;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
131
|
+
if ('url' in target)
|
|
132
|
+
return full.replace(`src="${href}"`, `src="${escapeXmlAttr(target.url)}"`);
|
|
133
|
+
const alt = /\balt="([^"]*)"/.exec(full)?.[1];
|
|
134
|
+
return `<ac:image${alt ? ` ac:alt="${escapeXmlAttr(unescapeHtml(alt))}"` : ''}><ri:attachment ri:filename="${escapeXmlAttr(target.attachment)}" /></ac:image>`;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
if (opts.linkResolver || opts.resourceResolver) {
|
|
138
|
+
html = html.replace(/<a href="([^"]*)"(?:\s+title="[^"]*")?>([\s\S]*?)<\/a>/g, (full, href, inner) => {
|
|
139
|
+
const decoded = unescapeHtml(href);
|
|
140
|
+
if (/^(?:[a-z][a-z0-9+.-]*:|#|\/\/)/i.test(decoded))
|
|
141
|
+
return full; // http(s):, mailto:, #anchor
|
|
142
|
+
const target = opts.linkResolver?.(decoded);
|
|
143
|
+
const body = /<[^>]+>/.test(inner)
|
|
144
|
+
? `<ac:link-body>${inner}</ac:link-body>`
|
|
145
|
+
: plainTextLinkBody(unescapeHtml(inner));
|
|
146
|
+
if (target) {
|
|
147
|
+
const space = target.space ? ` ri:space-key="${escapeXmlAttr(target.space)}"` : '';
|
|
148
|
+
const anchor = decoded.includes('#') ? ` ac:anchor="${escapeXmlAttr(decoded.slice(decoded.indexOf('#') + 1))}"` : '';
|
|
149
|
+
return `<ac:link${anchor}><ri:page ri:content-title="${escapeXmlAttr(target.title)}"${space} />${body}</ac:link>`;
|
|
150
|
+
}
|
|
151
|
+
const resource = opts.resourceResolver?.(decoded);
|
|
152
|
+
if (!resource)
|
|
153
|
+
return full;
|
|
154
|
+
if ('url' in resource)
|
|
155
|
+
return `<a href="${escapeXmlAttr(resource.url)}">${inner}</a>`;
|
|
156
|
+
return `<ac:link><ri:attachment ri:filename="${escapeXmlAttr(resource.attachment)}" />${body}</ac:link>`;
|
|
139
157
|
});
|
|
140
158
|
}
|
|
141
159
|
return html.replace(PLACEHOLDER_RE, (_full, kind, rawBody) => {
|
package/package.json
CHANGED