mirror of https://github.com/sveltejs/svelte
parent
561ecf28ff
commit
61977f1d92
@ -1,140 +1,140 @@
|
|||||||
import entities from './entities';
|
import entities from './entities.js';
|
||||||
|
|
||||||
const windows_1252 = [
|
const windows_1252 = [
|
||||||
8364, 129, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249, 338, 141, 381, 143, 144, 8216,
|
8364, 129, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249, 338, 141, 381, 143, 144, 8216,
|
||||||
8217, 8220, 8221, 8226, 8211, 8212, 732, 8482, 353, 8250, 339, 157, 382, 376
|
8217, 8220, 8221, 8226, 8211, 8212, 732, 8482, 353, 8250, 339, 157, 382, 376
|
||||||
];
|
];
|
||||||
|
|
||||||
function reg_exp_entity(entity_name: string, is_attribute_value: boolean) {
|
/**
|
||||||
// https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state
|
* @param {string} entity_name
|
||||||
// doesn't decode the html entity which not ends with ; and next character is =, number or alphabet in attribute value.
|
* @param {boolean} is_attribute_value
|
||||||
if (is_attribute_value && !entity_name.endsWith(';')) {
|
*/
|
||||||
return `${entity_name}\\b(?!=)`;
|
function reg_exp_entity(entity_name, is_attribute_value) {
|
||||||
}
|
// https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state
|
||||||
return entity_name;
|
// doesn't decode the html entity which not ends with ; and next character is =, number or alphabet in attribute value.
|
||||||
|
if (is_attribute_value && !entity_name.endsWith(';')) {
|
||||||
|
return `${entity_name}\\b(?!=)`;
|
||||||
|
}
|
||||||
|
return entity_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_entity_pattern(is_attribute_value: boolean) {
|
/**
|
||||||
const reg_exp_num = '#(?:x[a-fA-F\\d]+|\\d+)(?:;)?';
|
* @param {boolean} is_attribute_value
|
||||||
const reg_exp_entities = Object.keys(entities).map((entity_name) =>
|
*/
|
||||||
reg_exp_entity(entity_name, is_attribute_value)
|
function get_entity_pattern(is_attribute_value) {
|
||||||
);
|
const reg_exp_num = '#(?:x[a-fA-F\\d]+|\\d+)(?:;)?';
|
||||||
|
const reg_exp_entities = Object.keys(entities).map((entity_name) => reg_exp_entity(entity_name, is_attribute_value));
|
||||||
const entity_pattern = new RegExp(`&(${reg_exp_num}|${reg_exp_entities.join('|')})`, 'g');
|
const entity_pattern = new RegExp(`&(${reg_exp_num}|${reg_exp_entities.join('|')})`, 'g');
|
||||||
|
return entity_pattern;
|
||||||
return entity_pattern;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const entity_pattern_content = get_entity_pattern(false);
|
const entity_pattern_content = get_entity_pattern(false);
|
||||||
const entity_pattern_attr_value = get_entity_pattern(true);
|
const entity_pattern_attr_value = get_entity_pattern(true);
|
||||||
|
|
||||||
export function decode_character_references(html: string, is_attribute_value: boolean) {
|
/**
|
||||||
const entity_pattern = is_attribute_value ? entity_pattern_attr_value : entity_pattern_content;
|
* @param {string} html
|
||||||
return html.replace(entity_pattern, (match, entity) => {
|
* @param {boolean} is_attribute_value
|
||||||
let code;
|
*/
|
||||||
|
export function decode_character_references(html, is_attribute_value) {
|
||||||
// Handle named entities
|
const entity_pattern = is_attribute_value ? entity_pattern_attr_value : entity_pattern_content;
|
||||||
if (entity[0] !== '#') {
|
return html.replace(entity_pattern, (match, entity) => {
|
||||||
code = entities[entity];
|
let code;
|
||||||
} else if (entity[1] === 'x') {
|
// Handle named entities
|
||||||
code = parseInt(entity.substring(2), 16);
|
if (entity[0] !== '#') {
|
||||||
} else {
|
code = entities[entity];
|
||||||
code = parseInt(entity.substring(1), 10);
|
}
|
||||||
}
|
else if (entity[1] === 'x') {
|
||||||
|
code = parseInt(entity.substring(2), 16);
|
||||||
if (!code) {
|
}
|
||||||
return match;
|
else {
|
||||||
}
|
code = parseInt(entity.substring(1), 10);
|
||||||
|
}
|
||||||
return String.fromCodePoint(validate_code(code));
|
if (!code) {
|
||||||
});
|
return match;
|
||||||
|
}
|
||||||
|
return String.fromCodePoint(validate_code(code));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const NUL = 0;
|
const NUL = 0;
|
||||||
|
|
||||||
// some code points are verboten. If we were inserting HTML, the browser would replace the illegal
|
// some code points are verboten. If we were inserting HTML, the browser would replace the illegal
|
||||||
// code points with alternatives in some cases - since we're bypassing that mechanism, we need
|
// code points with alternatives in some cases - since we're bypassing that mechanism, we need
|
||||||
// to replace them ourselves
|
// to replace them ourselves
|
||||||
//
|
//
|
||||||
// Source: http://en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters
|
// Source: http://en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters
|
||||||
function validate_code(code: number) {
|
|
||||||
// line feed becomes generic whitespace
|
|
||||||
if (code === 10) {
|
|
||||||
return 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ASCII range. (Why someone would use HTML entities for ASCII characters I don't know, but...)
|
|
||||||
if (code < 128) {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
// code points 128-159 are dealt with leniently by browsers, but they're incorrect. We need
|
|
||||||
// to correct the mistake or we'll end up with missing € signs and so on
|
|
||||||
if (code <= 159) {
|
|
||||||
return windows_1252[code - 128];
|
|
||||||
}
|
|
||||||
|
|
||||||
// basic multilingual plane
|
/**
|
||||||
if (code < 55296) {
|
* @param {number} code
|
||||||
return code;
|
*/
|
||||||
}
|
function validate_code(code) {
|
||||||
|
// line feed becomes generic whitespace
|
||||||
// UTF-16 surrogate halves
|
if (code === 10) {
|
||||||
if (code <= 57343) {
|
return 32;
|
||||||
return NUL;
|
}
|
||||||
}
|
// ASCII range. (Why someone would use HTML entities for ASCII characters I don't know, but...)
|
||||||
|
if (code < 128) {
|
||||||
// rest of the basic multilingual plane
|
return code;
|
||||||
if (code <= 65535) {
|
}
|
||||||
return code;
|
// code points 128-159 are dealt with leniently by browsers, but they're incorrect. We need
|
||||||
}
|
// to correct the mistake or we'll end up with missing € signs and so on
|
||||||
|
if (code <= 159) {
|
||||||
// supplementary multilingual plane 0x10000 - 0x1ffff
|
return windows_1252[code - 128];
|
||||||
if (code >= 65536 && code <= 131071) {
|
}
|
||||||
return code;
|
// basic multilingual plane
|
||||||
}
|
if (code < 55296) {
|
||||||
|
return code;
|
||||||
// supplementary ideographic plane 0x20000 - 0x2ffff
|
}
|
||||||
if (code >= 131072 && code <= 196607) {
|
// UTF-16 surrogate halves
|
||||||
return code;
|
if (code <= 57343) {
|
||||||
}
|
return NUL;
|
||||||
|
}
|
||||||
return NUL;
|
// rest of the basic multilingual plane
|
||||||
|
if (code <= 65535) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
// supplementary multilingual plane 0x10000 - 0x1ffff
|
||||||
|
if (code >= 65536 && code <= 131071) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
// supplementary ideographic plane 0x20000 - 0x2ffff
|
||||||
|
if (code >= 131072 && code <= 196607) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
return NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// based on http://developers.whatwg.org/syntax.html#syntax-tag-omission
|
// based on http://developers.whatwg.org/syntax.html#syntax-tag-omission
|
||||||
const disallowed_contents = new Map([
|
const disallowed_contents = new Map([
|
||||||
['li', new Set(['li'])],
|
['li', new Set(['li'])],
|
||||||
['dt', new Set(['dt', 'dd'])],
|
['dt', new Set(['dt', 'dd'])],
|
||||||
['dd', new Set(['dt', 'dd'])],
|
['dd', new Set(['dt', 'dd'])],
|
||||||
[
|
[
|
||||||
'p',
|
'p',
|
||||||
new Set(
|
new Set('address article aside blockquote div dl fieldset footer form h1 h2 h3 h4 h5 h6 header hgroup hr main menu nav ol p pre section table ul'.split(' '))
|
||||||
'address article aside blockquote div dl fieldset footer form h1 h2 h3 h4 h5 h6 header hgroup hr main menu nav ol p pre section table ul'.split(
|
],
|
||||||
' '
|
['rt', new Set(['rt', 'rp'])],
|
||||||
)
|
['rp', new Set(['rt', 'rp'])],
|
||||||
)
|
['optgroup', new Set(['optgroup'])],
|
||||||
],
|
['option', new Set(['option', 'optgroup'])],
|
||||||
['rt', new Set(['rt', 'rp'])],
|
['thead', new Set(['tbody', 'tfoot'])],
|
||||||
['rp', new Set(['rt', 'rp'])],
|
['tbody', new Set(['tbody', 'tfoot'])],
|
||||||
['optgroup', new Set(['optgroup'])],
|
['tfoot', new Set(['tbody'])],
|
||||||
['option', new Set(['option', 'optgroup'])],
|
['tr', new Set(['tr', 'tbody'])],
|
||||||
['thead', new Set(['tbody', 'tfoot'])],
|
['td', new Set(['td', 'th', 'tr'])],
|
||||||
['tbody', new Set(['tbody', 'tfoot'])],
|
['th', new Set(['td', 'th', 'tr'])]
|
||||||
['tfoot', new Set(['tbody'])],
|
|
||||||
['tr', new Set(['tr', 'tbody'])],
|
|
||||||
['td', new Set(['td', 'th', 'tr'])],
|
|
||||||
['th', new Set(['td', 'th', 'tr'])]
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// can this be a child of the parent element, or does it implicitly
|
// can this be a child of the parent element, or does it implicitly
|
||||||
// close it, like `<li>one<li>two`?
|
// close it, like `<li>one<li>two`?
|
||||||
export function closing_tag_omitted(current: string, next?: string) {
|
|
||||||
if (disallowed_contents.has(current)) {
|
|
||||||
if (!next || disallowed_contents.get(current).has(next)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
/**
|
||||||
|
* @param {string} current
|
||||||
|
* @param {string} next
|
||||||
|
*/
|
||||||
|
export function closing_tag_omitted(current, next) {
|
||||||
|
if (disallowed_contents.has(current)) {
|
||||||
|
if (!next || disallowed_contents.get(current).has(next)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in new issue