Skip to content

Commit

Permalink
Allow sanitizing options, ensure links don't double on /, don't mod…
Browse files Browse the repository at this point in the history
…ify base64 links, make test results match universal GitHub links
  • Loading branch information
confused-Techie committed Oct 27, 2023
1 parent 2db34e2 commit cbaa3ad
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 8 deletions.
6 changes: 4 additions & 2 deletions packages/markdown-preview/lib/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ exports.toDOMFragment = async function (text, filePath, grammar, callback) {
{
renderMode: "fragment",
filePath: filePath,
breaks: atom.config.get('markdown-preview.breakOnSingleNewline')
breaks: atom.config.get('markdown-preview.breakOnSingleNewline'),
sanitizeAllowUnknownProtocols: atom.config.get('markdown-preview.allowUnsafeProtocols')
}
);
const domHTMLFragment = atom.ui.markdown.convertToDOM(domFragment);
Expand Down Expand Up @@ -73,7 +74,8 @@ exports.toHTML = async function (text, filePath, grammar) {
{
renderMode: "full",
filePath: filePath,
breaks: atom.config.get('markdown-preview.breakOnSingleNewline')
breaks: atom.config.get('markdown-preview.breakOnSingleNewline'),
sanitizeAllowUnknownProtocols: atom.config.get('markdown-preview.allowUnsafeProtocols')
}
);
const domHTMLFragment = atom.ui.markdown.convertToDOM(domFragment);
Expand Down
2 changes: 1 addition & 1 deletion packages/settings-view/spec/package-detail-view-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ describe("PackageDetailView", function() {
expect(view.element.querySelectorAll('.package-readme iframe').length).toBe(0);
expect(view.element.querySelectorAll('.package-readme input[type="checkbox"][disabled]').length).toBe(2);
expect(view.element.querySelector('img[alt="AbsoluteImage"]').getAttribute('src')).toBe('https://example.com/static/image.jpg');
expect(view.element.querySelector('img[alt="RelativeImage"]').getAttribute('src')).toBe('https://github.com/example/package-with-readme/blob/master/static/image.jpg');
expect(view.element.querySelector('img[alt="RelativeImage"]').getAttribute('src')).toBe('https://github.com/example/package-with-readme/raw/HEAD/static/image.jpg');
expect(view.element.querySelector('img[alt="Base64Image"]').getAttribute('src')).toBe('data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==');
});

Expand Down
20 changes: 15 additions & 5 deletions src/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ const mdComponents = {
currentDir: new RegExp(/^\.\//),
rootDir: new RegExp(/^\//)
},
globalLinks: {
base64: new RegExp(/^data:image\/.*;base64/, "i");
},
atomLinks: {
package: new RegExp(/^https:\/\/atom\.io\/packages\/(.*)$/),
flightManual: new RegExp(/^https:\/\/flight-manual\.atom\.io\//)
Expand All @@ -32,6 +35,8 @@ function renderMarkdown(content, givenOpts = {}) {
// Valid values: 'full', 'fragment'
html: true, // Enable HTML tags in source
sanitize: true, // Enable or disable sanitization
sanitizeAllowUnknownProtocols: true,
sanitizeAllowSelfClose: true,
breaks: false, // Convert `\n` in paragraphs into `<br>`
handleFrontMatter: true, // Determines if Front Matter content should be parsed
useDefaultEmoji: true, // Use `markdown-it-emoji`
Expand Down Expand Up @@ -160,11 +165,11 @@ function renderMarkdown(content, givenOpts = {}) {
// Fix any links that attempt to point to packages on `https://atom.io/packages/...`
attr[1] = `https://web.pulsar-edit.dev/packages/${link.match(mdComponents.reg.atomLinks.package)[1]}`;
} else if (opts.transformNonFqdnLinks && mdComponents.reg.localLinks.currentDir.test(link)) {
attr[1] = `${cleanRootDomain()}/raw/HEAD/${link.replace(mdComponents.reg.localLinks.currentDir, "")}`;
attr[1] = `${cleanRootDomain().replace(/\/$/, "")}/raw/HEAD/${link.replace(mdComponents.reg.localLinks.currentDir, "")}`;
} else if (opts.transformNonFqdnLinks && mdComponents.reg.localLinks.rootDir.test(link)) {
attr[1] = `${cleanRootDomain()}/raw/HEAD/${link.replace(mdComponents.reg.localLinks.rootDir, "")}`;
} else if (opts.transformNonFqdnLinks && !link.startsWith("http")) {
attr[1] = `${cleanRootDomain()}/raw/HEAD/${link.replace(".git", "")}`;
attr[1] = `${cleanRootDomain().replace(/\/$/, "")}/raw/HEAD/${link.replace(mdComponents.reg.localLinks.rootDir, "")}`;
} else if (opts.transformNonFqdnLinks && !link.startsWith("http") && !mdComponents.reg.globalLinks.base64.test(link)) {
attr[1] = `${cleanRootDomain().replace(/\/$/, "")}/raw/HEAD/${link.replace(".git", "")}`;
} else if (opts.transformAtomLinks && mdComponents.reg.atomLinks.flightManual.test(link)) {
// Resolve any links to the flight manual to web archive
attr[1] = link.replace(mdComponents.reg.atomLinks.flightManual, "https://web.archive.org/web/20221215003438/https://flight-manual.atom.io/");
Expand Down Expand Up @@ -368,7 +373,12 @@ function renderMarkdown(content, givenOpts = {}) {
if (opts.sanitize) {
mdComponents.deps.domPurify ??= require("dompurify");

rendered = mdComponents.deps.domPurify.sanitize(rendered);
let domPurifyOpts = {
ALLOW_UNKNOWN_PROTOCOLS: opts.sanitizeAllowUnknownProtocols
ALLOW_SELF_CLOSE_IN_ATTR: opts.sanitizeAllowSelfClose
};

rendered = mdComponents.deps.domPurify.sanitize(rendered, opts);
}

return rendered;
Expand Down

0 comments on commit cbaa3ad

Please sign in to comment.