Skip to content

Commit 099b442

Browse files
committed
chore(ci): upstream update
1 parent bef5bc9 commit 099b442

File tree

3 files changed

+682
-409
lines changed

3 files changed

+682
-409
lines changed

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="utf-8" />
55
<meta name="apple-mobile-web-app-capable" content="yes" />
6-
<meta name="generator" content="slidesdown 1.2.5" />
6+
<meta name="generator" content="slidesdown 1.2.6" />
77
<link href="https://slidesdown.github.io" rel="canonical" />
88
<meta content="Slidesdown" property="og:title" />
99
<meta content="Presentations at the speed of Markdown" name="description" />

plugin/slidesdown.js

Lines changed: 78 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,16 @@ function addAttributeInElement(node, elementTarget, separator) {
6666
const attrsInNode = new RegExp(separator, "gm");
6767
const attrsRegex = new RegExp(
6868
// attributes are limited to prevent code injection
69-
"(?:^|\s)(?<attr>class|style|data-[a-z-]+)=(?:\"(?<dval>[^\"]+?)\"|'(?<sval>[^']+?)')",
69+
/(?:^|\s+)(?<attr>class|style|data-[a-z-]+)=(?:"(?<dval>[^"]+?)"|'(?<sval>[^']+?)')/,
7070
"gm",
7171
);
7272
let matches,
7373
matchesAttrs;
7474
if ((matches = attrsInNode.exec(node.nodeValue)) !== null) {
7575
const attrs = matches[1];
76+
// remove match from comment node to avoid further processing
77+
node.nodeValue = node.nodeValue.substring(0, matches.index) +
78+
node.nodeValue.substring(attrsInNode.lastIndex);
7679
while ((matchesAttrs = attrsRegex.exec(attrs)) !== null) {
7780
elementTarget.setAttribute(
7881
matchesAttrs.groups.attr,
@@ -134,14 +137,19 @@ function addAttributes(
134137
}
135138
}
136139
if (element.nodeType == Node.COMMENT_NODE) {
140+
let attrs_added = false;
141+
// Avoid adding attributes to the section if separatorElementAttributes is used
137142
if (previousElement !== section) {
138-
addAttributeInElement(
143+
attrs_added = addAttributeInElement(
139144
element,
140145
previousElement,
141146
separatorElementAttributes,
142147
);
143148
}
144-
addAttributeInElement(element, section, separatorSectionAttributes);
149+
// Speed optimization: only add attributes if they haven't been added before
150+
if (!attrs_added) {
151+
addAttributeInElement(element, section, separatorSectionAttributes);
152+
}
145153
}
146154
}
147155

@@ -159,6 +167,69 @@ function addSlidifyDefaultOptions(options) {
159167
return options;
160168
}
161169

170+
const IS_URL = /^https?:\/\//;
171+
const IS_ABSOLUTE = /^\//;
172+
const IS_LOCAL = /^#/;
173+
const IS_RELATIVE = /^(\.\.\/|\.\/)/;
174+
175+
/**
176+
* Takes an HTML marked token and converts relative URLs in img, a and comment elements into absolute URLs.
177+
*/
178+
function rebasePathIfNeeded(base_url, token) {
179+
let text = [];
180+
let last_index = 0;
181+
let remainder = "";
182+
const a_href_regex =
183+
/((<a[^>]* href=")([^"]*)("[^>]*>)|(<a[^>]* href=')([^']*)('[^>]*>))/gi;
184+
const img_src_regex =
185+
/((<img[^>]* src=")([^"]*)("[^>]*>)|(<img[^>]* src=')([^']*)('[^>]*>))/gi;
186+
const img_data_preview_image_regex =
187+
/((<img[^>]* data-preview-image=")([^"]*)("[^>]*>)|(<img[^>]* data-preview-image=')([^']*)('[^>]*>))/gi;
188+
const data_background_image_regex =
189+
/((\sdata-background-image=")([^"]*)(")|(\sdata-background-image=')([^']*)('))/gi;
190+
// data-background-image
191+
for (
192+
const regex of [
193+
a_href_regex,
194+
img_src_regex,
195+
img_data_preview_image_regex,
196+
data_background_image_regex,
197+
]
198+
) {
199+
for (const match of token.text.matchAll(regex)) {
200+
// offset to select between single or double qoutes path in regex
201+
const matchOffset = match[2] ? 0 : 3;
202+
text.push(token.text.substring(last_index, match.index));
203+
const ref = match[3 + matchOffset];
204+
const needsRebase =
205+
!(IS_URL.test(ref) || IS_ABSOLUTE.test(ref) || IS_LOCAL.test(ref));
206+
// const needsRebase = isRelative.test(ref);
207+
let rebasing = "";
208+
let path_url = "";
209+
if (needsRebase) {
210+
rebasing = base_url;
211+
}
212+
if (needsRebase) {
213+
// Normalize URL if it needs rebasing
214+
path_url = new URL(`${rebasing}${match[3 + matchOffset]}`).toString();
215+
} else {
216+
path_url = `${rebasing}${match[3 + matchOffset]}`;
217+
}
218+
text.push(
219+
`${match[2 + matchOffset]}${path_url}${match[4 + matchOffset]}`,
220+
);
221+
last_index = match.index + match[0].length;
222+
}
223+
if (text.length) {
224+
remainder = token.text.substring(last_index, token.text.length);
225+
token.text = text.join("") + remainder;
226+
}
227+
text = [];
228+
last_index = 0;
229+
}
230+
return { text, last_index, remainder };
231+
}
232+
162233
export function buildMarkedConfiguration(markedOptions) {
163234
// Marked options: https://marked.js.org/using_advanced#options
164235
// baseUrl for html elements a and img
@@ -174,15 +245,6 @@ export function buildMarkedConfiguration(markedOptions) {
174245
marked.use(gfmHeadingId());
175246
markedOptions.async = true;
176247
markedOptions.useNewRenderer = true;
177-
const a_href_regex =
178-
/((<a[^>]*? href=")([^"]*?)("[^>]*?>)|(<a[^>]*? href=')([^']+?)('[^>]*?>))/gi;
179-
// TODO: apply img src also to data-preview-image
180-
const img_src_regex =
181-
/((<img[^>]*? src=")([^"]*?)("[^>]*?>)|(<img[^>]*? src=')([^']+?)('[^>]*?>))/gi;
182-
const isUrl = /^https?:\/\//;
183-
const isAbsolute = /^\//;
184-
const isLocal = /^#/;
185-
const isRelative = /^(\.\.\/|\.\/)/;
186248
const markedConfig = {
187249
...markedOptions,
188250
renderer: {
@@ -192,58 +254,10 @@ export function buildMarkedConfiguration(markedOptions) {
192254
},
193255
walkTokens: (token) => {
194256
if (token.type === "html") {
195-
let text = [];
196-
let last_index = 0;
197-
let remainder = "";
198-
for (const match of token.text.matchAll(img_src_regex)) {
199-
const matchOffset = match[2] ? 0 : 3;
200-
text.push(token.text.substring(last_index, match.index));
201-
const ref = match[3 + matchOffset];
202-
const needsRebase =
203-
!(isUrl.test(ref) || isAbsolute.test(ref) || isLocal.test(ref));
204-
// const needsRebase = isRelative.test(ref);
205-
if (needsRebase) {
206-
text.push(
207-
`${match[2 + matchOffset]}${base_url}${match[3 + matchOffset]}${
208-
match[4 + matchOffset]
209-
}`,
210-
);
211-
} else {
212-
text.push(
213-
`${match[2 + matchOffset]}${match[3 + matchOffset]}${
214-
match[4 + matchOffset]
215-
}`,
216-
);
217-
}
218-
last_index = match.index + match[0].length;
219-
}
220-
if (text.length) {
221-
remainder = token.text.substring(last_index, token.text.length);
222-
token.text = text.join("") + remainder;
223-
}
224-
text = [];
225-
last_index = 0;
226-
for (const match of token.text.matchAll(a_href_regex)) {
227-
text.push(token.text.substring(last_index, match.index));
228-
const matchOffset = match[2] ? 0 : 3;
229-
const ref = match[3 + matchOffset];
230-
// const needsRebase = !(isUrl.test(ref) || isAbsolute.test(ref) || isLocal.test(ref))
231-
const needsRebase = isRelative.test(ref);
232-
if (needsRebase) {
233-
text.push(
234-
`${match[2 + matchOffset]}${base_url}${match[3 + matchOffset]}${
235-
match[4 + matchOffset]
236-
}`,
237-
);
238-
} else {
239-
text.push(
240-
`${match[2 + matchOffset]}${match[3 + matchOffset]}${
241-
match[4 + matchOffset]
242-
}`,
243-
);
244-
}
245-
last_index = match.index + match[0].length;
246-
}
257+
let { text, last_index, remainder } = rebasePathIfNeeded(
258+
base_url,
259+
token,
260+
);
247261
if (text.length) {
248262
remainder = token.text.substring(last_index, token.text.length);
249263
token.text = text.join("") + remainder;

0 commit comments

Comments
 (0)