feat(css-parser): add better diagnostic for font-face
MODIFY
internal/css-parser/parser/font.ts
internal/css-parser/parser/font.ts
@@ -2,15 +2,33 @@ import {CSSParser} from "@internal/css-parser/types";
import {CSSFontFace} from "@internal/ast/css/font/CSSFontFace";
import {matchToken, readToken} from "@internal/css-parser/tokenizer";
import {parseDeclarationBlock} from "@internal/css-parser/parser/declaration";
+import {descriptions} from "@internal/diagnostics";
export function parseFontFace(parser: CSSParser): CSSFontFace | undefined {
const start = parser.getPosition();
-
+ const fontFaceToken = parser.getPreviousToken();
+ let sourceFound: boolean = false;
while (matchToken(parser, "Whitespace")) {
readToken(parser, "Whitespace");
}
- const block = parseDeclarationBlock({parser});
+ const block = parseDeclarationBlock({
+ parser,
+ onAtDeclaration: (token) => {
+ if (token.value === "src") {
+ sourceFound = true;
+ }
+ return true;
+ },
+ });
+
+ if (!sourceFound) {
+ parser.unexpectedDiagnostic({
+ description: descriptions.CSS_PARSER.AT_FONT_FACE_MISSING_SRC,
+ token: fontFaceToken,
+ });
+ return undefined;
+ }
if (block) {
return parser.finishNode(

ADD
internal/css-parser/test-fixtures/invalid/font/input.css
+@font-face {
+ font-display: block;
+}

ADD
internal/css-parser/test-fixtures/invalid/font/input.test.md
+# `index.test.ts`
+
+**DO NOT MODIFY**. This file has been autogenerated. Run `rome test internal/css-parser/index.test.ts --update-snapshots` to update.
+
+## `invalid > font`
+
+```javascript
+CSSRoot {
+ body: [
+ CSSAtRule {
+ name: "font-face"
+ prelude: []
+ loc: SourceLocation invalid/font/input.css 1:0-3:1
+ }
+ ]
+ comments: []
+ corrupt: false
+ diagnostics: [
+ {
+ origins: [{entity: "ParserCore<css>"}]
+ description: {
+ advice: []
+ category: ["parse"]
+ categoryValue: "css"
+ message: RAW_MARKUP {value: "The rule <emphasis>@font-face</emphasis> needs the property <emphasis>src</emphasis> in order to be valid."}
+ }
+ location: {
+ language: "css"
+ path: RelativePath<invalid/font/input.css>
+ end: Position 1:10
+ start: Position 1:0
+ }
+ }
+ ]
+ path: RelativePath<invalid/font/input.css>
+ loc: SourceLocation invalid/font/input.css 1:0-3:1
+}
+```

MODIFY
internal/css-parser/tokenizer/index.ts
internal/css-parser/tokenizer/index.ts
-import {AnyCSSToken, CSSParser, Tokens} from "../types";
+import {AnyCSSToken, CSSParser} from "../types";
type TokenType = AnyCSSToken["type"];
function skipComments(parser: CSSParser) {
while (parser.matchToken("Comment")) {
const start = parser.getPosition();
- const token = parser.eatToken("Comment") as Tokens["Comment"];
+ const token = parser.eatToken("Comment");
+ if (token) {
parser.registerComment(
parser.comments.createComment({
type: "CommentBlock",
@@ -15,6 +16,7 @@ function skipComments(parser: CSSParser) {
);
}
}
+}
export function nextToken(parser: CSSParser) {
skipComments(parser);

MODIFY
internal/diagnostics/descriptions/parsers/cssParser.ts
internal/diagnostics/descriptions/parsers/cssParser.ts
@@ -202,4 +202,8 @@ export const cssParser = createDiagnosticsCategory({
{minRating: 0, ignoreCase: false},
),
}),
+
+ AT_FONT_FACE_MISSING_SRC: {
+ message: markup`The rule <emphasis>@font-face</emphasis> needs the property <emphasis>src</emphasis> in order to be valid.`,
+ },
});

feat(css-parser): add better diagnostic for font-face (#1433)