DuyTa's picture
Upload folder using huggingface_hub
bc20498 verified
raw
history blame
2.82 kB
// @ts-ignore
// import parse from 'css-tree/parser'; // When css-tree supports container queries uncomment.
import { parse } from './css-tree-cq/css_tree_parse.js'; // Use extended css-tree for container query support.
import { walk } from 'estree-walker';
import parser_errors from '../errors.js';
const regex_closing_style_tag = /<\/style\s*>/;
const regex_starts_with_closing_style_tag = /^<\/style\s*>/;
/**
*
* @param {import('../index.js').Parser} parser
* @param {number} start
* @param {import('estree').Node[]} attributes
* @returns {import('../../interfaces.js').Style}
*/
export default function read_style(parser, start, attributes) {
const content_start = parser.index;
const styles = parser.read_until(regex_closing_style_tag, parser_errors.unclosed_style);
if (parser.index >= parser.template.length) {
parser.error(parser_errors.unclosed_style);
}
const content_end = parser.index;
// discard styles when css is disabled
if (parser.css_mode === 'none') {
parser.read(regex_starts_with_closing_style_tag);
return null;
}
let ast;
try {
ast = parse(styles, {
positions: true,
offset: content_start,
onParseError(error) {
throw error;
}
});
} catch (err) {
if (err.name === 'SyntaxError') {
parser.error(parser_errors.css_syntax_error(err.message), err.offset);
} else {
throw err;
}
}
ast = JSON.parse(JSON.stringify(ast));
// tidy up AST
walk(ast, {
/** @param {any} node */
enter: (node) => {
// `any` because this isn't an ESTree node
// replace `ref:a` nodes
if (node.type === 'Selector') {
for (let i = 0; i < node.children.length; i += 1) {
const a = node.children[i];
const b = node.children[i + 1];
if (is_ref_selector(a, b)) {
parser.error(parser_errors.invalid_ref_selector, a.loc.start.offset);
}
}
}
if (
node.type === 'Declaration' &&
node.value.type === 'Value' &&
node.value.children.length === 0
) {
parser.error(parser_errors.invalid_declaration, node.start);
}
if (node.type === 'PseudoClassSelector' && node.name === 'global' && node.children === null) {
parser.error(parser_errors.empty_global_selector, node.loc.start.offset);
}
if (node.loc) {
node.start = node.loc.start.offset;
node.end = node.loc.end.offset;
delete node.loc;
}
}
});
parser.read(regex_starts_with_closing_style_tag);
const end = parser.index;
return {
type: 'Style',
start,
end,
attributes,
children: ast.children,
content: {
start: content_start,
end: content_end,
styles
}
};
}
/**
* @param {any} a
* @param {any} b
*/
function is_ref_selector(a, b) {
// TODO add CSS node types
if (!b) return false;
return a.type === 'TypeSelector' && a.name === 'ref' && b.type === 'PseudoClassSelector';
}