Skip to content

Commit fe510b9

Browse files
committed
add more at rules
1 parent e78deae commit fe510b9

8 files changed

Lines changed: 456 additions & 9 deletions

File tree

src/parse/index.ts

Lines changed: 214 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import {
66
type CssCommentAST,
77
type CssCommonPositionAST,
88
type CssContainerAST,
9+
type CssCounterStyleAST,
910
type CssCustomMediaAST,
1011
type CssDeclarationAST,
1112
type CssDocumentAST,
1213
type CssFontFaceAST,
14+
type CssFontFeatureValuesAST,
1315
type CssGenericAtRuleAST,
1416
type CssHostAST,
1517
type CssImportAST,
@@ -19,10 +21,14 @@ import {
1921
type CssMediaAST,
2022
type CssNamespaceAST,
2123
type CssPageAST,
24+
type CssPositionTryAST,
25+
type CssPropertyAST,
2226
type CssRuleAST,
27+
type CssScopeAST,
2328
type CssStartingStyleAST,
2429
type CssStylesheetAST,
2530
type CssSupportsAST,
31+
type CssViewTransitionAST,
2632
CssTypes,
2733
} from '../type';
2834
import {
@@ -688,14 +694,26 @@ export const parse = (
688694
if (!open()) {
689695
return error("@page missing '{'");
690696
}
691-
let decls = comments<CssDeclarationAST>();
697+
const decls: Array<CssDeclarationAST | CssCommentAST | CssAtRuleAST> = [];
698+
comments(decls);
692699

693-
// declarations
694-
let decl: CssDeclarationAST | undefined = declaration();
695-
while (decl) {
696-
decls.push(decl);
697-
decls = decls.concat(comments());
698-
decl = declaration();
700+
// declarations and nested at-rules (margin boxes)
701+
while (css.length && css.charAt(0) !== '}') {
702+
if (css.charAt(0) === '@') {
703+
const ar = atRule();
704+
if (ar) {
705+
decls.push(ar);
706+
comments(decls);
707+
continue;
708+
}
709+
}
710+
const decl = declaration();
711+
if (decl) {
712+
decls.push(decl);
713+
comments(decls);
714+
continue;
715+
}
716+
break;
699717
}
700718

701719
if (!close()) {
@@ -775,6 +793,189 @@ export const parse = (
775793
});
776794
}
777795

796+
/**
797+
* Parse @property.
798+
*/
799+
function atProperty(): CssPropertyAST | undefined {
800+
const pos = position();
801+
const m = /^@property\s+(--[-\w]+)\s*/.exec(css);
802+
if (!m) {
803+
return;
804+
}
805+
const name = processMatch(m)[1];
806+
807+
if (!open()) {
808+
return error("@property missing '{'");
809+
}
810+
let decls = comments<CssDeclarationAST>();
811+
let decl: CssDeclarationAST | undefined = declaration();
812+
while (decl) {
813+
decls.push(decl);
814+
decls = decls.concat(comments());
815+
decl = declaration();
816+
}
817+
if (!close()) {
818+
return error("@property missing '}'");
819+
}
820+
821+
return pos<CssPropertyAST>({
822+
type: CssTypes.property,
823+
name: name,
824+
declarations: decls,
825+
});
826+
}
827+
828+
/**
829+
* Parse @counter-style.
830+
*/
831+
function atCounterStyle(): CssCounterStyleAST | undefined {
832+
const pos = position();
833+
const m = /^@counter-style\s+([-\w]+)\s*/.exec(css);
834+
if (!m) {
835+
return;
836+
}
837+
const name = processMatch(m)[1];
838+
839+
if (!open()) {
840+
return error("@counter-style missing '{'");
841+
}
842+
let decls = comments<CssDeclarationAST>();
843+
let decl: CssDeclarationAST | undefined = declaration();
844+
while (decl) {
845+
decls.push(decl);
846+
decls = decls.concat(comments());
847+
decl = declaration();
848+
}
849+
if (!close()) {
850+
return error("@counter-style missing '}'");
851+
}
852+
853+
return pos<CssCounterStyleAST>({
854+
type: CssTypes.counterStyle,
855+
name: name,
856+
declarations: decls,
857+
});
858+
}
859+
860+
/**
861+
* Parse @font-feature-values.
862+
*/
863+
function atFontFeatureValues(): CssFontFeatureValuesAST | undefined {
864+
const pos = position();
865+
const m = /^@font-feature-values\s+([^{]+)/.exec(css);
866+
if (!m) {
867+
return;
868+
}
869+
const fontFamily = trim(processMatch(m)[1]);
870+
871+
if (!open()) {
872+
return error("@font-feature-values missing '{'");
873+
}
874+
875+
const style = rulesOrDeclarations();
876+
877+
if (!close()) {
878+
return error("@font-feature-values missing '}'");
879+
}
880+
881+
return pos<CssFontFeatureValuesAST>({
882+
type: CssTypes.fontFeatureValues,
883+
fontFamily: fontFamily,
884+
rules: style,
885+
});
886+
}
887+
888+
/**
889+
* Parse @scope.
890+
*/
891+
function atScope(): CssScopeAST | undefined {
892+
const pos = position();
893+
const m = /^@scope\s*([^{]*)/.exec(css);
894+
if (!m) {
895+
return;
896+
}
897+
const scope = trim(processMatch(m)[1]);
898+
899+
if (!open()) {
900+
return error("@scope missing '{'");
901+
}
902+
903+
const style = rulesOrDeclarations();
904+
905+
if (!close()) {
906+
return error("@scope missing '}'");
907+
}
908+
909+
return pos<CssScopeAST>({
910+
type: CssTypes.scope,
911+
scope: scope,
912+
rules: style,
913+
});
914+
}
915+
916+
/**
917+
* Parse @view-transition.
918+
*/
919+
function atViewTransition(): CssViewTransitionAST | undefined {
920+
const pos = position();
921+
const m = /^@view-transition\s*/.exec(css);
922+
if (!m) {
923+
return;
924+
}
925+
processMatch(m);
926+
927+
if (!open()) {
928+
return error("@view-transition missing '{'");
929+
}
930+
let decls = comments<CssDeclarationAST>();
931+
let decl: CssDeclarationAST | undefined = declaration();
932+
while (decl) {
933+
decls.push(decl);
934+
decls = decls.concat(comments());
935+
decl = declaration();
936+
}
937+
if (!close()) {
938+
return error("@view-transition missing '}'");
939+
}
940+
941+
return pos<CssViewTransitionAST>({
942+
type: CssTypes.viewTransition,
943+
declarations: decls,
944+
});
945+
}
946+
947+
/**
948+
* Parse @position-try.
949+
*/
950+
function atPositionTry(): CssPositionTryAST | undefined {
951+
const pos = position();
952+
const m = /^@position-try\s+(--[-\w]+)\s*/.exec(css);
953+
if (!m) {
954+
return;
955+
}
956+
const name = processMatch(m)[1];
957+
958+
if (!open()) {
959+
return error("@position-try missing '{'");
960+
}
961+
let decls = comments<CssDeclarationAST>();
962+
let decl: CssDeclarationAST | undefined = declaration();
963+
while (decl) {
964+
decls.push(decl);
965+
decls = decls.concat(comments());
966+
decl = declaration();
967+
}
968+
if (!close()) {
969+
return error("@position-try missing '}'");
970+
}
971+
972+
return pos<CssPositionTryAST>({
973+
type: CssTypes.positionTry,
974+
name: name,
975+
declarations: decls,
976+
});
977+
}
978+
778979
/**
779980
* Parse starting style.
780981
*/
@@ -913,9 +1114,15 @@ export const parse = (
9131114
atPage() ||
9141115
atHost() ||
9151116
atFontFace() ||
1117+
atFontFeatureValues() ||
9161118
atContainer() ||
9171119
atStartingStyle() ||
9181120
atLayer() ||
1121+
atProperty() ||
1122+
atCounterStyle() ||
1123+
atScope() ||
1124+
atViewTransition() ||
1125+
atPositionTry() ||
9191126
atGeneric()
9201127
);
9211128
}

0 commit comments

Comments
 (0)