Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix merged html attribute quoting #2235

Merged
merged 4 commits into from
Oct 30, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 16 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
## Master
## [master]

New languages:
none.

New styles:
none.

Improvements:
- fix(parser): Fix merger HTML attribute quoting (#2235) [Josh Goebel][]

[Josh Goebel]: https://github.com/yyyc514


## Version 9.16.0


New languages:
none.
Expand Down
4 changes: 3 additions & 1 deletion src/highlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ https://highlightjs.org/
}

function open(node) {
function attr_str(a) {return ' ' + a.nodeName + '="' + escape(a.value).replace('"', '"') + '"';}
function attr_str(a) {
return ' ' + a.nodeName + '="' + escape(a.value).replace(/"/g, '"') + '"';
}
result += '<' + tag(node) + ArrayProto.map.call(node.attributes, attr_str).join('') + '>';
}

Expand Down
41 changes: 28 additions & 13 deletions test/browser/plain.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,35 @@ const {promisify} = require('util');
const glob = promisify(require('glob'));
const fs = require('fs');

describe('plain browser', function() {
before(function() {
// Will match both `highlight.pack.js` and `highlight.min.js`
const filepath = utility.buildPath('..', 'build', 'highlight.*.js');

return glob(filepath)
.then(hljsPath => hljsPath.map(path => fs.readFileSync(path, 'utf8')))
.then(hljsFiles => hljsFiles.map(file => `<script>${file}</script>`).join(""))
.then(hljsScript => new JSDOM(hljsScript + this.html, { runScripts: "dangerously" }))
.then(({ window }) => {
this.block = window.document.querySelector('pre code');
this.hljs = window.hljs;
});
const buildFakeDOM = async function() {
// Will match both `highlight.pack.js` and `highlight.min.js`
const filePath = utility.buildPath('..', 'build', 'highlight.*.js');
const hljsPath = await glob(filePath)
const hljsFiles = await hljsPath.map(path => fs.readFileSync(path, 'utf8'))
const hljsScript = await hljsFiles.map(file => `<script>${file}</script>`).join("")
const { window} = await new JSDOM(hljsScript + this.html, { runScripts: "dangerously" })

this.block = window.document.querySelector('pre code');
this.hljs = window.hljs;
};

describe('browser with html with quotes in attributes', function() {
it('should property escape all quotes', async function() {
this.text = "const oops = pick(employee, <span data-title=\" Type '&quot;height&quot;' is not assignable to type '&quot;name&quot; | &quot;age'&quot; | &quot;profession&quot;'.\">['name', 'height']</span>)\n"
this.html = `<pre><code class="javascript">${this.text}</code></pre>`;

// can't use before because we need to do setup first
await buildFakeDOM.bind(this)();

this.hljs.highlightBlock(this.block);
const actual = this.block.innerHTML;
actual.should.equal(
`<span class="hljs-keyword">const</span> oops = pick(employee, <span data-title=" Type '&quot;height&quot;' is not assignable to type '&quot;name&quot; | &quot;age'&quot; | &quot;profession&quot;'.">[<span class="hljs-string">'name'</span>, <span class="hljs-string">'height'</span>]</span>)\n`);
});
})

describe('plain browser', function() {
before(async function() { await buildFakeDOM.bind(this)(); });

it('should return relevance key', function() {
var out = this.hljs.highlight("javascript","");
Expand Down