UNPKG

html2canvas-pro

Version:

Screenshots with JavaScript. Next generation!

190 lines 7.35 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.clipPath = void 0; const parser_1 = require("../syntax/parser"); const length_percentage_1 = require("../types/length-percentage"); const NONE = { type: 0 /* CLIP_PATH_TYPE.NONE */ }; /** * Parse a shape-radius token: <length-percentage> | closest-side | farthest-side. * Defaults to 'closest-side' when no tokens are provided. */ const parseShapeRadius = (tokens) => { const [first] = tokens; if (!first) return 'closest-side'; if ((0, parser_1.isIdentToken)(first)) { // Any unrecognised keyword (e.g. 'closest-corner') intentionally falls back to // 'closest-side' as the CSS spec requires unknown values to be treated as invalid // and the initial value of <shape-radius> is 'closest-side'. return first.value === 'farthest-side' ? 'farthest-side' : 'closest-side'; } return (0, length_percentage_1.isLengthPercentage)(first) ? first : 'closest-side'; }; /** * Parse a CSS <position> as (cx, cy), each as a LengthPercentage. * * Supports the **1–2 value** subset of the CSS `<position>` syntax. * The 4-value form (`at left 10px top 20px`) is not supported and will be * parsed on a best-effort basis. * * Axis assignment rules: * - `left` / `right` → x-axis (cx) * - `top` / `bottom` → y-axis (cy) * - `center` or a <length-percentage> → fills the first unset axis, in order * * Examples: * "at left" → cx=0, cy=50% (left is x; y defaults to center) * "at top" → cx=50%, cy=0 (top is y; x defaults to center) * "at center 30%" → cx=50%, cy=30% * "at 30% center" → cx=30%, cy=50% * "at left top" → cx=0, cy=0 * "at top left" → cx=0, cy=0 (keyword order is irrelevant) * * Unset axes fall back to 50%. */ const parsePosition = (tokens) => { let cx = null; let cy = null; for (const token of tokens) { if ((0, parser_1.isIdentToken)(token)) { switch (token.value) { case 'left': cx = length_percentage_1.ZERO_LENGTH; break; case 'right': cx = length_percentage_1.HUNDRED_PERCENT; break; case 'top': cy = length_percentage_1.ZERO_LENGTH; break; case 'bottom': cy = length_percentage_1.HUNDRED_PERCENT; break; case 'center': // `center` fills whichever axis has not yet been claimed. if (cx === null) cx = length_percentage_1.FIFTY_PERCENT; else if (cy === null) cy = length_percentage_1.FIFTY_PERCENT; break; } } else if ((0, length_percentage_1.isLengthPercentage)(token)) { // Length-percentages are assigned in source order. if (cx === null) cx = token; else if (cy === null) cy = token; } } return { cx: cx ?? length_percentage_1.FIFTY_PERCENT, cy: cy ?? length_percentage_1.FIFTY_PERCENT }; }; /** * inset( <length-percentage>{1,4} [ round <'border-radius'> ]? ) * The 1-4 shorthand follows the same expansion as margin/padding: * 1 value → all four sides * 2 values → top/bottom | left/right * 3 values → top | left/right | bottom * 4 values → top | right | bottom | left * The optional `round` clause (border-radius) is parsed but ignored. */ const parseInset = (values) => { const lengths = []; for (const token of values) { if (token.type === 31 /* TokenType.WHITESPACE_TOKEN */) continue; if ((0, parser_1.isIdentToken)(token) && token.value === 'round') break; if ((0, length_percentage_1.isLengthPercentage)(token)) lengths.push(token); } const v0 = lengths[0] ?? length_percentage_1.ZERO_LENGTH; const v1 = lengths[1] ?? v0; const v2 = lengths[2] ?? v0; const v3 = lengths[3] ?? v1; return { type: 1 /* CLIP_PATH_TYPE.INSET */, top: v0, right: v1, bottom: v2, left: v3 }; }; /** * circle( [ <shape-radius> ]? [ at <position> ]? ) */ const parseCircle = (values) => { const nonWs = values.filter(parser_1.nonWhiteSpace); const atIdx = nonWs.findIndex((t) => (0, parser_1.isIdentWithValue)(t, 'at')); const radiusTokens = atIdx === -1 ? nonWs : nonWs.slice(0, atIdx); const posTokens = atIdx === -1 ? [] : nonWs.slice(atIdx + 1); return { type: 2 /* CLIP_PATH_TYPE.CIRCLE */, radius: parseShapeRadius(radiusTokens), ...parsePosition(posTokens) }; }; /** * ellipse( [ <shape-radius>{2} ]? [ at <position> ]? ) */ const parseEllipse = (values) => { const nonWs = values.filter(parser_1.nonWhiteSpace); const atIdx = nonWs.findIndex((t) => (0, parser_1.isIdentWithValue)(t, 'at')); const radiusTokens = atIdx === -1 ? nonWs : nonWs.slice(0, atIdx); const posTokens = atIdx === -1 ? [] : nonWs.slice(atIdx + 1); return { type: 3 /* CLIP_PATH_TYPE.ELLIPSE */, rx: parseShapeRadius(radiusTokens.slice(0, 1)), ry: parseShapeRadius(radiusTokens.slice(1, 2)), ...parsePosition(posTokens) }; }; /** * polygon( [ <fill-rule>, ]? [ <length-percentage> <length-percentage> ]# ) * Each comma-separated group defines one vertex (x y). * A leading fill-rule keyword (nonzero/evenodd) is skipped. */ const parsePolygon = (values) => { const args = (0, parser_1.parseFunctionArgs)(values); const points = []; for (const arg of args) { if (arg.length === 1 && (0, parser_1.isIdentToken)(arg[0])) continue; // skip fill-rule const lengths = arg.filter(length_percentage_1.isLengthPercentage); if (lengths.length >= 2) { points.push([lengths[0], lengths[1]]); } } return { type: 4 /* CLIP_PATH_TYPE.POLYGON */, points }; }; /** * path( [ <fill-rule>, ]? <string> ) * The string value is the SVG path data (coordinates in the element's local space). */ const parsePath = (values) => { const stringToken = values.find((t) => t.type === 0 /* TokenType.STRING_TOKEN */); if (!stringToken) return NONE; return { type: 5 /* CLIP_PATH_TYPE.PATH */, d: stringToken.value }; }; exports.clipPath = { name: 'clip-path', initialValue: 'none', prefix: false, type: 0 /* PropertyDescriptorParsingType.VALUE */, parse: (_context, token) => { if ((0, parser_1.isIdentToken)(token) && token.value === 'none') { return NONE; } if (token.type === 18 /* TokenType.FUNCTION */) { switch (token.name) { case 'inset': return parseInset(token.values); case 'circle': return parseCircle(token.values); case 'ellipse': return parseEllipse(token.values); case 'polygon': return parsePolygon(token.values); case 'path': return parsePath(token.values); } } return NONE; } }; //# sourceMappingURL=clip-path.js.map