Add tests for markdown content escaping (#4058)

This commit is contained in:
Matthew Phillips 2022-07-26 17:31:57 -04:00 committed by GitHub
parent c57242d534
commit da5e6ca128
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 50 additions and 20 deletions

View file

@ -82,7 +82,7 @@
"test:e2e:match": "playwright test -g" "test:e2e:match": "playwright test -g"
}, },
"dependencies": { "dependencies": {
"@astrojs/compiler": "^0.22.0", "@astrojs/compiler": "^0.22.1",
"@astrojs/language-server": "^0.20.0", "@astrojs/language-server": "^0.20.0",
"@astrojs/markdown-remark": "^0.13.0", "@astrojs/markdown-remark": "^0.13.0",
"@astrojs/prism": "0.6.1", "@astrojs/prism": "0.6.1",

View file

@ -0,0 +1,3 @@
# Lesser than: Cannot escape `<` using `&lt;`
&lt;i&gt;This should NOT be italic&lt;/i&gt;

View file

@ -3,28 +3,39 @@ import * as cheerio from 'cheerio';
import { loadFixture } from './test-utils.js'; import { loadFixture } from './test-utils.js';
describe('Markdown tests', () => { describe('Markdown tests', () => {
/** @type {import('./test-utils').Fixture} */
let fixture; let fixture;
before(async () => { before(async () => {
fixture = await loadFixture({ fixture = await loadFixture({
root: './fixtures/markdown/', root: './fixtures/markdown/',
}); });
await fixture.build();
}); });
it('Can load a simple markdown page with Astro', async () => { describe('Build', () => {
const html = await fixture.readFile('/post/index.html'); before(async () => {
const $ = cheerio.load(html); await fixture.build();
});
it('Can load a simple markdown page with Astro', async () => {
const html = await fixture.readFile('/post/index.html');
const $ = cheerio.load(html);
expect($('p').first().text()).to.equal('Hello world!');
expect($('#first').text()).to.equal('Some content');
expect($('#interesting-topic').text()).to.equal('Interesting Topic');
});
it('Can load a realworld markdown page with Astro', async () => {
const html = await fixture.readFile('/realworld/index.html');
const $ = cheerio.load(html);
expect($('pre')).to.have.lengthOf(7);
});
expect($('p').first().text()).to.equal('Hello world!'); it('Does not unescape entities', async () => {
expect($('#first').text()).to.equal('Some content'); const html = await fixture.readFile('/entities/index.html');
expect($('#interesting-topic').text()).to.equal('Interesting Topic'); expect(html).to.match(new RegExp("&#x3C;i>This should NOT be italic&#x3C;/i>"));
}); });
it('Can load a realworld markdown page with Astro', async () => {
const html = await fixture.readFile('/realworld/index.html');
const $ = cheerio.load(html);
expect($('pre')).to.have.lengthOf(7);
}); });
}); });

View file

@ -1,5 +1,9 @@
import { visit } from 'unist-util-visit'; import { visit } from 'unist-util-visit';
export function escapeEntities(value: string): string {
return value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
export default function rehypeEscape(): any { export default function rehypeEscape(): any {
return function (node: any): any { return function (node: any): any {
return visit(node, 'element', (el) => { return visit(node, 'element', (el) => {
@ -8,7 +12,7 @@ export default function rehypeEscape(): any {
// Visit all raw children and escape HTML tags to prevent Markdown code // Visit all raw children and escape HTML tags to prevent Markdown code
// like "This is a `<script>` tag" from actually opening a script tag // like "This is a `<script>` tag" from actually opening a script tag
visit(el, 'raw', (raw) => { visit(el, 'raw', (raw) => {
raw.value = raw.value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;'); raw.value = escapeEntities(raw.value);
}); });
} }
return el; return el;

View file

@ -0,0 +1,12 @@
import { renderMarkdown } from '../dist/index.js';
import { expect } from 'chai';
describe('entities', () => {
const renderAstroMd = (text) => renderMarkdown(text, { isAstroFlavoredMd: false });
it('should not unescape entities', async () => {
const { code } = await renderAstroMd(`&lt;i&gt;This should NOT be italic&lt;/i&gt;`);
expect(code).to.equal(`<p>&#x3C;i>This should NOT be italic&#x3C;/i></p>`);
});
});

View file

@ -438,7 +438,7 @@ importers:
packages/astro: packages/astro:
specifiers: specifiers:
'@astrojs/compiler': ^0.22.0 '@astrojs/compiler': ^0.22.1
'@astrojs/language-server': ^0.20.0 '@astrojs/language-server': ^0.20.0
'@astrojs/markdown-remark': ^0.13.0 '@astrojs/markdown-remark': ^0.13.0
'@astrojs/prism': 0.6.1 '@astrojs/prism': 0.6.1
@ -526,7 +526,7 @@ importers:
yargs-parser: ^21.0.1 yargs-parser: ^21.0.1
zod: ^3.17.3 zod: ^3.17.3
dependencies: dependencies:
'@astrojs/compiler': 0.22.0 '@astrojs/compiler': 0.22.1
'@astrojs/language-server': 0.20.1 '@astrojs/language-server': 0.20.1
'@astrojs/markdown-remark': link:../markdown/remark '@astrojs/markdown-remark': link:../markdown/remark
'@astrojs/prism': link:../astro-prism '@astrojs/prism': link:../astro-prism
@ -2962,8 +2962,8 @@ packages:
leven: 3.1.0 leven: 3.1.0
dev: true dev: true
/@astrojs/compiler/0.22.0: /@astrojs/compiler/0.22.1:
resolution: {integrity: sha512-TF3zwbPIgr3UPPkVquKUzSGsIqGKh3Gi34Y29+HZvL+YmrkAk+GAuUkOo2EXDJ6aS2Oxq0k7KO/yQ2LjkWl83A==} resolution: {integrity: sha512-FiRZ7fwJhADPo2X1unTyEq9V7EfeWE3GOBhzKDcFIF8mc5iLZ0VmPXrGmvOUTRXkZH99+TkB1SXGaTDjelRa2w==}
dev: false dev: false
/@astrojs/language-server/0.20.1: /@astrojs/language-server/0.20.1: