Brunobkr/llama.cpp_AlgMor24_github
ΩFFFΣLLIa • llama.cpp • AlgMor24 ██████╗ ███████╗███████╗███████╗██╗ ██╗ ██╗ █████╗ ██╔═══██╗██╔════╝██╔════╝██╔════╝██║ ██║ ██║██╔══██╗ ██║ ██║█████╗ █████╗ █████╗ ██║ ██║ ██║███████║ ██║ ██║██╔══╝ ██╔══╝ ██╔══╝ ██║ ██║ ██║██╔══██║ ╚██████╔╝██║ ██║ ███████╗███████╗███████╗██║██║ ██║ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝ High-Performance LLM / VLM Inference & Autonomous Agentic Ecosystem… See the full description on the dataset page: https://huggingface.co/datasets/Brunobkr/llama.cpp_AlgMor24_github.
03.1k
1import CssParseError from '../CssParseError';2import Position from '../CssPosition';3import {4 type CssAtRuleAST,5 type CssCharsetAST,6 type CssCommentAST,7 type CssCommonPositionAST,8 type CssContainerAST,9 type CssCounterStyleAST,10 type CssCustomMediaAST,11 type CssDeclarationAST,12 type CssDocumentAST,13 type CssFontFaceAST,14 type CssFontFeatureValuesAST,15 type CssGenericAtRuleAST,16 type CssHostAST,17 type CssImportAST,18 type CssKeyframeAST,19 type CssKeyframesAST,20 type CssLayerAST,21 type CssMediaAST,22 type CssNamespaceAST,23 type CssPageAST,24 type CssPageMarginBoxAST,25 type CssPositionTryAST,26 type CssPropertyAST,27 type CssRuleAST,28 type CssScopeAST,29 type CssStartingStyleAST,30 type CssStylesheetAST,31 type CssSupportsAST,32 CssTypes,33 type CssViewTransitionAST,34} from '../type';35import {36 indexOfArrayWithBracketAndQuoteSupport,37 splitWithBracketAndQuoteSupport,38} from '../utils/stringSearch';39 40// http://www.w3.org/TR/CSS21/grammar.html41// https://github.com/visionmedia/css-parse/pull/49#issuecomment-3008802742// New rule => https://www.w3.org/TR/CSS22/syndata.html#comments43// [^] is equivalent to [.\n\r]44const commentRegex = /\/\*[^]*?(?:\*\/|$)/g;45 46export const parse = (47 css: string,48 options?: { source?: string; silent?: boolean },49): CssStylesheetAST => {50 options = options || {};51 52 /**53 * Positional.54 */55 let lineno = 1;56 let column = 1;57 58 /**59 * Update lineno and column based on `str`.60 */61 function updatePosition(str: string) {62 const lines = str.match(/\n/g);63 if (lines) {64 lineno += lines.length;65 }66 const i = str.lastIndexOf('\n');67 column = ~i ? str.length - i : column + str.length;68 }69 70 /**71 * Mark position and patch `node.position`.72 */73 function position() {74 const start = { line: lineno, column: column };75 return <T1 extends CssCommonPositionAST>(76 node: Omit<T1, 'position'>,77 ): T1 => {78 (node as T1).position = new Position(79 start,80 { line: lineno, column: column },81 options?.source || '',82 );83 whitespace();84 return node as T1;85 };86 }87 88 /**89 * Error `msg`.90 */91 const errorsList: Array<CssParseError> = [];92 93 function error(msg: string): undefined {94 const err = new CssParseError(95 options?.source || '',96 msg,97 lineno,98 column,99 css,100 );101 102 if (options?.silent) {103 errorsList.push(err);104 } else {105 throw err;106 }107 }108 109 /**110 * Parse stylesheet.111 */112 function stylesheet(): CssStylesheetAST {113 const rulesList = rules();114 115 const result: CssStylesheetAST = {116 type: CssTypes.stylesheet,117 stylesheet: {118 source: options?.source,119 rules: rulesList,120 parsingErrors: errorsList,121 },122 };123 124 return result;125 }126 127 /**128 * Opening brace.129 */130 function open(): boolean {131 const openMatch = /^{\s*/.exec(css);132 if (openMatch) {133 processMatch(openMatch);134 return true;135 }136 return false;137 }138 139 /**140 * Closing brace.141 */142 function close() {143 const closeMatch = /^}/.exec(css);144 if (closeMatch) {145 processMatch(closeMatch);146 return true;147 }148 return false;149 }150 151 /**152 * Parse ruleset.153 */154 function rules() {155 let node: CssRuleAST | CssAtRuleAST | undefined;156 const rules: Array<CssRuleAST | CssAtRuleAST> = [];157 whitespace();158 comments(rules);159 while (css.length) {160 if (css.charAt(0) === '}') {161 if (options?.silent) {162 // Skip stray closing braces at top level163 error("extra '}'");164 const fakeMatch = ['}'] as unknown as RegExpExecArray;165 processMatch(fakeMatch);166 whitespace();167 comments(rules);168 continue;169 }170 break;171 }172 node = atRule() || rule();173 if (node) {174 rules.push(node);175 comments(rules);176 } else {177 if (options?.silent) {178 // Skip unrecognized character to recover179 const fakeMatch = [css.charAt(0)] as unknown as RegExpExecArray;180 processMatch(fakeMatch);181 whitespace();182 comments(rules);183 continue;184 }185 break;186 }187 }188 return rules;189 }190 191 /**192 * Update position and css string. Return the matches193 */194 function processMatch(m: RegExpExecArray) {195 const str = m[0];196 updatePosition(str);197 css = css.slice(str.length);198 return m;199 }200 201 /**202 * Parse whitespace.203 */204 function whitespace() {205 const m = /^\s*/.exec(css);206 if (m) {207 processMatch(m);208 }209 }210 211 /**212 * Parse comments;213 */214 function comments<T1 extends CssCommonPositionAST>(215 rules?: Array<T1 | CssCommentAST>,216 ) {217 rules = rules || [];218 let c: CssCommentAST | undefined = comment();219 while (c) {220 rules.push(c);221 c = comment();222 }223 return rules;224 }225 226 /**227 * Parse comment.228 */229 function comment(): CssCommentAST | undefined {230 const pos = position();231 if ('/' !== css.charAt(0) || '*' !== css.charAt(1)) {232 return;233 }234 235 const m = /^\/\*[^]*?\*\//.exec(css);236 if (!m) {237 return error('End of comment missing');238 }239 processMatch(m);240 241 return pos<CssCommentAST>({242 type: CssTypes.comment,243 comment: m[0].slice(2, -2),244 });245 }246 247 /**248 * Parse selector.249 */250 function selector() {251 const bracePos = indexOfArrayWithBracketAndQuoteSupport(css, ['{']);252 if (bracePos === -1 || bracePos === 0) {253 return;254 }255 const selectorStr = css.substring(0, bracePos);256 const fakeMatch = [selectorStr] as unknown as RegExpExecArray;257 processMatch(fakeMatch);258 259 // remove comment in selector;260 const res = trim(selectorStr).replace(commentRegex, '');261 262 return splitWithBracketAndQuoteSupport(res, [',']).map((v) => trim(v));263 }264 265 /**266 * Parse declaration.267 */268 function declaration(): CssDeclarationAST | undefined {269 const pos = position();270 271 // prop272 const propMatch = /^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/.exec(css);273 if (!propMatch) {274 return;275 }276 processMatch(propMatch);277 const propValue = trim(propMatch[0]);278 279 // :280 const separatorMatch = /^:\s*/.exec(css);281 if (!separatorMatch) {282 return error("property missing ':'");283 }284 processMatch(separatorMatch);285 286 // val287 let value = '';288 const endValuePosition = indexOfArrayWithBracketAndQuoteSupport(css, [289 ';',290 '}',291 ]);292 if (endValuePosition !== -1) {293 value = css.substring(0, endValuePosition);294 const fakeMatch = [value] as unknown as RegExpExecArray;295 processMatch(fakeMatch);296 297 value = trim(value).replace(commentRegex, '');298 }299 300 const ret = pos<CssDeclarationAST>({301 type: CssTypes.declaration,302 property: propValue.replace(commentRegex, ''),303 value: value,304 });305 306 // ;307 const endMatch = /^[;\s]*/.exec(css);308 if (endMatch) {309 processMatch(endMatch);310 }311 312 return ret;313 }314 315 /**316 * Parse declarations (without nesting support).317 * Used by @font-face, @page, keyframes.318 */319 function declarations() {320 const decls: Array<CssDeclarationAST | CssCommentAST> = [];321 322 if (!open()) {323 return error("missing '{'");324 }325 comments(decls);326 327 // declarations328 let decl: CssDeclarationAST | undefined = declaration();329 while (decl) {330 decls.push(decl);331 comments(decls);332 decl = declaration();333 }334 // In silent mode, try to recover from errors by skipping to next semicolon335 while (options?.silent && css.length && css.charAt(0) !== '}') {336 const semiPos = css.indexOf(';');337 const bracePos = css.indexOf('}');338 if (semiPos !== -1 && (bracePos === -1 || semiPos < bracePos)) {339 const fakeMatch = [340 css.substring(0, semiPos + 1),341 ] as unknown as RegExpExecArray;342 processMatch(fakeMatch);343 whitespace();344 comments(decls);345 decl = declaration();346 while (decl) {347 decls.push(decl);348 comments(decls);349 decl = declaration();350 }351 } else {352 break;353 }354 }355 356 if (!close()) {357 return error("missing '}'");358 }359 return decls;360 }361 362 /**363 * Check if the current position looks like a nested rule364 * ('{' appears before ';' and '}' at the top level).365 */366 function looksLikeNestedRule(): boolean {367 const bracePos = indexOfArrayWithBracketAndQuoteSupport(css, ['{']);368 if (bracePos === -1) {369 return false;370 }371 const semiPos = indexOfArrayWithBracketAndQuoteSupport(css, [';']);372 const closePos = indexOfArrayWithBracketAndQuoteSupport(css, ['}']);373 374 if (semiPos !== -1 && semiPos < bracePos) {375 return false;376 }377 if (closePos !== -1 && closePos < bracePos) {378 return false;379 }380 return true;381 }382 383 /**384 * Parse rule body with CSS nesting support.385 * Handles declarations, comments, nested rules, and nested at-rules.386 */387 function ruleBody():388 | Array<CssDeclarationAST | CssCommentAST | CssAtRuleAST>389 | undefined {390 const items: Array<CssDeclarationAST | CssCommentAST | CssAtRuleAST> = [];391 392 if (!open()) {393 return error("missing '{'");394 }395 comments(items);396 397 while (css.length && css.charAt(0) !== '}') {398 // nested at-rule399 if (css.charAt(0) === '@') {400 const ar = atRule();401 if (ar) {402 items.push(ar);403 comments(items);404 continue;405 }406 }407 408 // nested rule ('{' comes before ';' and '}')409 if (looksLikeNestedRule()) {410 const nestedR = rule();411 if (nestedR) {412 items.push(nestedR);413 comments(items);414 continue;415 }416 }417 418 // declaration419 const decl = declaration();420 if (decl) {421 items.push(decl);422 comments(items);423 continue;424 }425 426 // nothing matched — skip to next semicolon or closing brace to recover427 if (options?.silent) {428 const semiPos = css.indexOf(';');429 const bracePos = css.indexOf('}');430 if (semiPos !== -1 && (bracePos === -1 || semiPos < bracePos)) {431 const fakeMatch = [432 css.substring(0, semiPos + 1),433 ] as unknown as RegExpExecArray;434 processMatch(fakeMatch);435 whitespace();436 comments(items);437 continue;438 }439 }440 break;441 }442 443 if (!close()) {444 return error("missing '}'");445 }446 return items;447 }448 449 /**450 * Parse rules, declarations, and nested rules.451 * Used by block at-rules (media, supports, etc.) to support452 * both top-level rules and declarations when nested inside a rule.453 */454 function rulesOrDeclarations() {455 const items: Array<CssAtRuleAST | CssDeclarationAST | CssCommentAST> = [];456 whitespace();457 comments(items);458 while (css.length && css.charAt(0) !== '}') {459 // at-rule460 if (css.charAt(0) === '@') {461 const ar = atRule();462 if (ar) {463 items.push(ar);464 comments(items);465 continue;466 }467 }468 469 // nested rule ('{' comes before ';' and '}')470 if (looksLikeNestedRule()) {471 const r = rule();472 if (r) {473 items.push(r);474 comments(items);475 continue;476 }477 }478 479 // declaration480 const decl = declaration();481 if (decl) {482 items.push(decl);483 comments(items);484 continue;485 }486 487 // nothing matched — skip to next semicolon or closing brace to recover488 if (options?.silent) {489 const semiPos = css.indexOf(';');490 const bracePos = css.indexOf('}');491 if (semiPos !== -1 && (bracePos === -1 || semiPos < bracePos)) {492 const fakeMatch = [493 css.substring(0, semiPos + 1),494 ] as unknown as RegExpExecArray;495 processMatch(fakeMatch);496 whitespace();497 comments(items);498 continue;499 }500 }501 break;502 }503 return items;504 }505 506 /**507 * Parse keyframe.508 */509 function keyframe() {510 const vals = [];511 const pos = position();512 513 let m: RegExpExecArray | null = /^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/.exec(514 css,515 );516 while (m) {517 const res = processMatch(m);518 vals.push(res[1]);519 const spacesMatch = /^,\s*/.exec(css);520 if (spacesMatch) {521 processMatch(spacesMatch);522 }523 m = /^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/.exec(css);524 }525 526 if (!vals.length) {527 return;528 }529 530 return pos<CssKeyframeAST>({531 type: CssTypes.keyframe,532 values: vals,533 declarations: declarations() || [],534 });535 }536 537 /**538 * Parse keyframes.539 */540 function atKeyframes(): CssKeyframesAST | undefined {541 const pos = position();542 const m1 = /^@([-\w]+)?keyframes\s*/.exec(css);543 544 if (!m1) {545 return;546 }547 const vendor = processMatch(m1)[1];548 549 // identifier550 const m2 = /^([-\w]+)\s*/.exec(css);551 if (!m2) {552 return error('@keyframes missing name');553 }554 const name = processMatch(m2)[1];555 556 if (!open()) {557 return error("@keyframes missing '{'");558 }559 560 let frames: Array<CssKeyframeAST | CssCommentAST> = comments();561 let frame: CssKeyframeAST | undefined = keyframe();562 while (frame) {563 frames.push(frame);564 frames = frames.concat(comments());565 frame = keyframe();566 }567 568 if (!close()) {569 return error("@keyframes missing '}'");570 }571 572 return pos<CssKeyframesAST>({573 type: CssTypes.keyframes,574 name: name,575 vendor: vendor,576 keyframes: frames,577 });578 }579 580 /**581 * Parse supports.582 */583 function atSupports(): CssSupportsAST | undefined {584 const pos = position();585 const m = /^@supports *([^{]+)/.exec(css);586 587 if (!m) {588 return;589 }590 const supports = trim(processMatch(m)[1]);591 592 if (!open()) {593 return error("@supports missing '{'");594 }595 596 const style = rulesOrDeclarations();597 598 if (!close()) {599 return error("@supports missing '}'");600 }601 602 return pos<CssSupportsAST>({603 type: CssTypes.supports,604 supports: supports,605 rules: style,606 });607 }608 609 /**610 * Parse host.611 */612 function atHost() {613 const pos = position();614 const m = /^@host\s*/.exec(css);615 616 if (!m) {617 return;618 }619 processMatch(m);620 621 if (!open()) {622 return error("@host missing '{'");623 }624 625 const style = rulesOrDeclarations();626 627 if (!close()) {628 return error("@host missing '}'");629 }630 631 return pos<CssHostAST>({632 type: CssTypes.host,633 rules: style,634 });635 }636 637 /**638 * Parse container.639 */640 function atContainer(): CssContainerAST | undefined {641 const pos = position();642 const m = /^@container *([^{]+)/.exec(css);643 644 if (!m) {645 return;646 }647 const container = trim(processMatch(m)[1]);648 649 if (!open()) {650 return error("@container missing '{'");651 }652 653 const style = rulesOrDeclarations();654 655 if (!close()) {656 return error("@container missing '}'");657 }658 659 return pos<CssContainerAST>({660 type: CssTypes.container,661 container: container,662 rules: style,663 });664 }665 666 /**667 * Parse container.668 */669 function atLayer(): CssLayerAST | undefined {670 const pos = position();671 const m = /^@layer *([^{;@]+)/.exec(css);672 673 if (!m) {674 return;675 }676 const layer = trim(processMatch(m)[1]);677 678 if (!open()) {679 const m2 = /^[;\s]*/.exec(css);680 if (m2) {681 processMatch(m2);682 }683 return pos<CssLayerAST>({684 type: CssTypes.layer,685 layer: layer,686 });687 }688 689 const style = rulesOrDeclarations();690 691 if (!close()) {692 return error("@layer missing '}'");693 }694 695 return pos<CssLayerAST>({696 type: CssTypes.layer,697 layer: layer,698 rules: style,699 });700 }701 702 /**703 * Parse media.704 */705 function atMedia(): CssMediaAST | undefined {706 const pos = position();707 const m = /^@media *([^{]+)/.exec(css);708 709 if (!m) {710 return;711 }712 const media = trim(processMatch(m)[1]);713 714 if (!open()) {715 return error("@media missing '{'");716 }717 718 const style = rulesOrDeclarations();719 720 if (!close()) {721 return error("@media missing '}'");722 }723 724 return pos<CssMediaAST>({725 type: CssTypes.media,726 media: media,727 rules: style,728 });729 }730 731 /**732 * Parse custom-media.733 */734 function atCustomMedia(): CssCustomMediaAST | undefined {735 const pos = position();736 const m = /^@custom-media\s+(--\S+)\s+([^{;\s][^{;]*);/.exec(css);737 if (!m) {738 return;739 }740 const res = processMatch(m);741 742 return pos<CssCustomMediaAST>({743 type: CssTypes.customMedia,744 name: trim(res[1]),745 media: trim(res[2]),746 });747 }748 749 /**750 * Parse @page margin box at-rules (@top-left, @bottom-right, @left-middle, etc.).751 */752 const pageMarginBoxNames = [753 'top-left-corner',754 'top-left',755 'top-center',756 'top-right',757 'top-right-corner',758 'bottom-left-corner',759 'bottom-left',760 'bottom-center',761 'bottom-right',762 'bottom-right-corner',763 'left-top',764 'left-middle',765 'left-bottom',766 'right-top',767 'right-middle',768 'right-bottom',769 ];770 const pageMarginBoxRegex = new RegExp(771 `^@(${pageMarginBoxNames.join('|')})(?![\\w-])\\s*`,772 );773 774 function atPageMarginBox(): CssPageMarginBoxAST | undefined {775 const pos = position();776 const m = pageMarginBoxRegex.exec(css);777 if (!m) {778 return;779 }780 const name = processMatch(m)[1];781 782 if (!open()) {783 return error(`@${name} missing '{'`);784 }785 let decls = comments<CssDeclarationAST>();786 let decl: CssDeclarationAST | undefined = declaration();787 while (decl) {788 decls.push(decl);789 decls = decls.concat(comments());790 decl = declaration();791 }792 if (!close()) {793 return error(`@${name} missing '}'`);794 }795 796 return pos<CssPageMarginBoxAST>({797 type: CssTypes.pageMarginBox,798 name: name,799 declarations: decls,800 });801 }802 803 /**804 * Parse paged media.805 */806 function atPage(): CssPageAST | undefined {807 const pos = position();808 const m = /^@page */.exec(css);809 if (!m) {810 return;811 }812 processMatch(m);813 814 const sel = selector() || [];815 816 if (!open()) {817 return error("@page missing '{'");818 }819 const decls: Array<CssDeclarationAST | CssCommentAST | CssAtRuleAST> = [];820 comments(decls);821 822 // declarations and nested at-rules (margin boxes)823 while (css.length && css.charAt(0) !== '}') {824 if (css.charAt(0) === '@') {825 const ar = atRule();826 if (ar) {827 decls.push(ar);828 comments(decls);829 continue;830 }831 }832 const decl = declaration();833 if (decl) {834 decls.push(decl);835 comments(decls);836 continue;837 }838 break;839 }840 841 if (!close()) {842 return error("@page missing '}'");843 }844 845 return pos<CssPageAST>({846 type: CssTypes.page,847 selectors: sel,848 declarations: decls,849 });850 }851 852 /**853 * Parse document.854 */855 function atDocument(): CssDocumentAST | undefined {856 const pos = position();857 const m = /^@([-\w]+)?document *([^{]+)/.exec(css);858 if (!m) {859 return;860 }861 const res = processMatch(m);862 863 const vendor = trim(res[1]);864 const doc = trim(res[2]);865 866 if (!open()) {867 return error("@document missing '{'");868 }869 870 const style = rulesOrDeclarations();871 872 if (!close()) {873 return error("@document missing '}'");874 }875 876 return pos<CssDocumentAST>({877 type: CssTypes.document,878 document: doc,879 vendor: vendor,880 rules: style,881 });882 }883 884 /**885 * Parse font-face.886 */887 function atFontFace(): CssFontFaceAST | undefined {888 const pos = position();889 const m = /^@font-face\s*/.exec(css);890 if (!m) {891 return;892 }893 processMatch(m);894 895 if (!open()) {896 return error("@font-face missing '{'");897 }898 let decls = comments<CssDeclarationAST>();899 900 // declarations901 let decl: CssDeclarationAST | undefined = declaration();902 while (decl) {903 decls.push(decl);904 decls = decls.concat(comments());905 decl = declaration();906 }907 908 if (!close()) {909 return error("@font-face missing '}'");910 }911 912 return pos<CssFontFaceAST>({913 type: CssTypes.fontFace,914 declarations: decls,915 });916 }917 918 /**919 * Parse @property.920 */921 function atProperty(): CssPropertyAST | undefined {922 const pos = position();923 const m = /^@property\s+(--[-\w]+)\s*/.exec(css);924 if (!m) {925 return;926 }927 const name = processMatch(m)[1];928 929 if (!open()) {930 return error("@property missing '{'");931 }932 let decls = comments<CssDeclarationAST>();933 let decl: CssDeclarationAST | undefined = declaration();934 while (decl) {935 decls.push(decl);936 decls = decls.concat(comments());937 decl = declaration();938 }939 if (!close()) {940 return error("@property missing '}'");941 }942 943 return pos<CssPropertyAST>({944 type: CssTypes.property,945 name: name,946 declarations: decls,947 });948 }949 950 /**951 * Parse @counter-style.952 */953 function atCounterStyle(): CssCounterStyleAST | undefined {954 const pos = position();955 const m = /^@counter-style\s+([-\w]+)\s*/.exec(css);956 if (!m) {957 return;958 }959 const name = processMatch(m)[1];960 961 if (!open()) {962 return error("@counter-style missing '{'");963 }964 let decls = comments<CssDeclarationAST>();965 let decl: CssDeclarationAST | undefined = declaration();966 while (decl) {967 decls.push(decl);968 decls = decls.concat(comments());969 decl = declaration();970 }971 if (!close()) {972 return error("@counter-style missing '}'");973 }974 975 return pos<CssCounterStyleAST>({976 type: CssTypes.counterStyle,977 name: name,978 declarations: decls,979 });980 }981 982 /**983 * Parse @font-feature-values.984 */985 function atFontFeatureValues(): CssFontFeatureValuesAST | undefined {986 const pos = position();987 const m = /^@font-feature-values\s+([^{]+)/.exec(css);988 if (!m) {989 return;990 }991 const fontFamily = trim(processMatch(m)[1]);992 993 if (!open()) {994 return error("@font-feature-values missing '{'");995 }996 997 const style = rulesOrDeclarations();998 999 if (!close()) {1000 return error("@font-feature-values missing '}'");1001 }1002 1003 return pos<CssFontFeatureValuesAST>({1004 type: CssTypes.fontFeatureValues,1005 fontFamily: fontFamily,1006 rules: style,1007 });1008 }1009 1010 /**1011 * Parse @scope.1012 */1013 function atScope(): CssScopeAST | undefined {1014 const pos = position();1015 const m = /^@scope\s*([^{]*)/.exec(css);1016 if (!m) {1017 return;1018 }1019 const scope = trim(processMatch(m)[1]);1020 1021 if (!open()) {1022 return error("@scope missing '{'");1023 }1024 1025 const style = rulesOrDeclarations();1026 1027 if (!close()) {1028 return error("@scope missing '}'");1029 }1030 1031 return pos<CssScopeAST>({1032 type: CssTypes.scope,1033 scope: scope,1034 rules: style,1035 });1036 }1037 1038 /**1039 * Parse @view-transition.1040 */1041 function atViewTransition(): CssViewTransitionAST | undefined {1042 const pos = position();1043 const m = /^@view-transition\s*/.exec(css);1044 if (!m) {1045 return;1046 }1047 processMatch(m);1048 1049 if (!open()) {1050 return error("@view-transition missing '{'");1051 }1052 let decls = comments<CssDeclarationAST>();1053 let decl: CssDeclarationAST | undefined = declaration();1054 while (decl) {1055 decls.push(decl);1056 decls = decls.concat(comments());1057 decl = declaration();1058 }1059 if (!close()) {1060 return error("@view-transition missing '}'");1061 }1062 1063 return pos<CssViewTransitionAST>({1064 type: CssTypes.viewTransition,1065 declarations: decls,1066 });1067 }1068 1069 /**1070 * Parse @position-try.1071 */1072 function atPositionTry(): CssPositionTryAST | undefined {1073 const pos = position();1074 const m = /^@position-try\s+(--[-\w]+)\s*/.exec(css);1075 if (!m) {1076 return;1077 }1078 const name = processMatch(m)[1];1079 1080 if (!open()) {1081 return error("@position-try missing '{'");1082 }1083 let decls = comments<CssDeclarationAST>();1084 let decl: CssDeclarationAST | undefined = declaration();1085 while (decl) {1086 decls.push(decl);1087 decls = decls.concat(comments());1088 decl = declaration();1089 }1090 if (!close()) {1091 return error("@position-try missing '}'");1092 }1093 1094 return pos<CssPositionTryAST>({1095 type: CssTypes.positionTry,1096 name: name,1097 declarations: decls,1098 });1099 }1100 1101 /**1102 * Parse starting style.1103 */1104 function atStartingStyle(): CssStartingStyleAST | undefined {1105 const pos = position();1106 const m = /^@starting-style\s*/.exec(css);1107 if (!m) {1108 return;1109 }1110 processMatch(m);1111 1112 if (!open()) {1113 return error("@starting-style missing '{'");1114 }1115 const style = rulesOrDeclarations();1116 1117 if (!close()) {1118 return error("@starting-style missing '}'");1119 }1120 1121 return pos<CssStartingStyleAST>({1122 type: CssTypes.startingStyle,1123 rules: style,1124 });1125 }1126 1127 /**1128 * Parse import1129 */1130 const atImport = _compileAtRule<CssImportAST>('import');1131 1132 /**1133 * Parse charset1134 */1135 const atCharset = _compileAtRule<CssCharsetAST>('charset');1136 1137 /**1138 * Parse namespace1139 */1140 const atNamespace = _compileAtRule<CssNamespaceAST>('namespace');1141 1142 /**1143 * Parse non-block at-rules1144 */1145 function _compileAtRule<T1 extends CssCommonPositionAST>(1146 name: string,1147 ): () => T1 | undefined {1148 const re = new RegExp(1149 '^@' +1150 name +1151 '\\s*((?::?[^;\'"]|"(?:\\\\"|[^"])*?"|\'(?:\\\\\'|[^\'])*?\')+)(?:;|$)',1152 );1153 1154 // ^@import\s*([^;"']|("|')(?:\\\2|.)*?\2)+(;|$)1155 1156 return (): T1 | undefined => {1157 const pos = position();1158 const m = re.exec(css);1159 if (!m) {1160 return;1161 }1162 const res = processMatch(m);1163 const ret: Record<string, string> = { type: name };1164 ret[name] = res[1].trim();1165 return pos<T1>(ret as unknown as T1) as T1;1166 };1167 }1168 1169 /**1170 * Parse generic/unknown at-rule (fallback for any unrecognized at-rule).1171 * Handles both block at-rules (@scope { ... }) and statement at-rules (@foo ...;).1172 */1173 function atGeneric(): CssGenericAtRuleAST | undefined {1174 const pos = position();1175 const m = /^@([-\w]+)\s*/.exec(css);1176 if (!m) {1177 return;1178 }1179 const name = processMatch(m)[1];1180 1181 // Capture prelude (everything between the name and '{' or ';')1182 let prelude = '';1183 const preludeEnd = indexOfArrayWithBracketAndQuoteSupport(css, ['{', ';']);1184 if (preludeEnd !== -1 && preludeEnd > 0) {1185 prelude = trim(css.substring(0, preludeEnd));1186 const fakeMatch = [1187 css.substring(0, preludeEnd),1188 ] as unknown as RegExpExecArray;1189 processMatch(fakeMatch);1190 }1191 1192 // Block at-rule1193 if (open()) {1194 const style = rulesOrDeclarations();1195 1196 if (!close()) {1197 return error(`@${name} missing '}'`);1198 }1199 1200 return pos<CssGenericAtRuleAST>({