1. 소개
이 섹션은 규범적인 내용이 아닙니다.
이 모듈은 CSS 스타일시트와 CSS 구문을 사용하는 기타 요소들(예: HTML style
속성)의 추상 구문과 파싱을 정의합니다.
이 모듈은 유니코드 코드 포인트 스트림(즉, 텍스트)을 CSS 토큰 스트림으로 변환하는 알고리즘과, 더 나아가 스타일시트, 규칙, 선언과 같은 CSS 객체로 변환하는 알고리즘을 정의합니다.
1.1. 모듈 상호작용
이 모듈은 CSS 스타일시트의 구문과 파싱을 정의하며, CSS 2.1에서 정의된 어휘 스캐너와 문법을 대체합니다.
2. CSS 구문 설명
이 섹션은 규범적인 내용이 아닙니다.
CSS 문서는 스타일 규칙—
한정 규칙은 프렐류드(prelude)로 시작하며,
중괄호({})로 감싸진 선언들의 시퀀스를 포함합니다.
프렐류드의 의미는 규칙이 등장하는 문맥에 따라 달라집니다—
일반적인 규칙 예시는 다음과 같습니다:
p > a { color: blue; text-decoration: underline; }
위 규칙에서 "p > a
"는 선택자이며,
소스 문서가 HTML이라면,
a
요소가
p
요소의 자식인 경우를 선택합니다.
"color: blue
"는 선택자에 해당하는 요소의 color
속성을 blue 값으로 지정합니다.
마찬가지로 text-decoration 속성은 underline 값이 됩니다.
at-규칙은 모두 다르지만, 기본 구조는 유사합니다. "@" 코드 포인트로 시작하여, 그 뒤에 CSS 키워드로 이름이 옵니다. 일부 at-규칙은 이름 뒤에 CSS 값을 더하여 동작을 지정하고, 마지막에 세미콜론으로 끝나는 단순 문장입니다. 다른 규칙들은 블록을 가지며, 이름 뒤에 CSS 값이 올 수 있지만, {}로 감싸진 블록으로 끝납니다. 한정 규칙과 유사합니다. 이 블록의 내용도 해당 at-규칙에 따라 다릅니다: 경우에 따라 한정 규칙처럼 선언의 시퀀스를 포함하거나, 추가 블록, at-규칙, 기타 구조를 포함할 수도 있습니다.
다양한 구문을 가진 at-규칙의 몇 가지 예시입니다.
@import "my-styles.css";
@import at-규칙은 단순 문장입니다. 이름 뒤에 스타일시트를 지정하는 문자열 또는 url() 함수를 받습니다.
@page :left { margin-left: 4cm; margin-right: 3cm; }
@page at-규칙은 선택적 페이지 선택자(:left 의사 클래스) 뒤에, 인쇄될 때 페이지에 적용되는 속성 블록이 옵니다. 일반 스타일 규칙과 매우 유사하지만, 속성이 "요소"가 아니라 페이지 자체에 적용된다는 점이 다릅니다.
@media print { body { font-size: 10pt } }
@media at-규칙은 미디어 타입과 선택적 미디어 쿼리 목록으로 시작합니다. 블록에는 전체 규칙이 들어가며, @media 조건이 충족될 때만 적용됩니다.
속성 이름과 at-규칙 이름은 항상 ident sequence입니다. 이는 ident-start 코드 포인트, 하이픈 두 개, 또는 하이픈과 ident-start 코드 포인트로 시작해야 하며, 그 뒤로 ident 코드 포인트가 0개 이상 올 수 있습니다. CSS 구문에 사용되는 코드 포인트라도, 이스케이프를 통해 포함시킬 수 있습니다.
선택자의 구문은 Selectors 명세에서 정의됩니다. 다양한 CSS 값의 구문 또한 Values & Units 명세에서 정의됩니다. 각 at-규칙의 특수 구문은 해당 명세에서 확인할 수 있습니다.
2.1. 이스케이프 처리
이 섹션은 규범적인 내용이 아닙니다.
모든 유니코드 코드 포인트는 ident sequence 또는 따옴표로 감싼 문자열에 이스케이프를 통해 포함될 수 있습니다. CSS 이스케이프 시퀀스는 역슬래시(\)로 시작하며, 다음 중 하나로 이어집니다:
- 코드 포인트 중 16진수 숫자나 줄바꿈 문자가 아닌 모든 유니코드 코드 포인트. 이스케이프 시퀀스는 해당 코드 포인트로 대체됩니다.
-
또는 1~6개의 16진수 숫자 뒤에 선택적 공백 문자가 옵니다.
이스케이프 시퀀스는 16진수 숫자로 지정된 값의 유니코드 코드 포인트로 대체됩니다.
이 선택적 공백은 16진수 이스케이프 시퀀스 뒤에 "실제" 16진수가 오도록 허용합니다.
"&B" 값을 가진 ident sequence는 \26 B 또는 \000026B로 쓸 수 있습니다.
이스케이프 시퀀스 뒤에 "실제" 공백이 오면 두 번 써야 합니다.
2.2. 오류 처리
이 섹션은 규범적인 내용이 아닙니다.
CSS에서 오류가 발생하면,
파서는 정상적으로 파싱으로 복귀하기 전 최소한의 내용만 버리고,
최대한 유연하게 복구를 시도합니다.
이는 오류가 항상 실수가 아니기 때문입니다—
정확한 오류 복구 동작은 파서에 자세히 기술되어 있지만, 간단하게 설명해도 충분히 정확합니다.
- 스타일시트의 "최상위"에서,
<at-keyword-token>은 at-규칙을 시작합니다.
그 외의 것은 한정 규칙을 시작하며,
규칙의 프렐류드에 포함됩니다.
이로 인해 유효하지 않은 선택자가 생성될 수 있지만,
이는 CSS 파서의 문제가 아닙니다—
최악의 경우, 선택자가 아무것도 매칭하지 않는다는 의미입니다. - at-규칙이 시작되면, 파서 관점에서는 아무것도 잘못된 것이 아닙니다; 모두 at-규칙의 프렐류드의 일부입니다. <semicolon-token>을 만나면 at-규칙이 즉시 끝나고, 중괄호 열기 <{-token>를 만나면 at-규칙의 본문이 시작됩니다. at-규칙은 괄호(), 중괄호{}, 대괄호[]로 둘러싸인 블록을 맞추며 앞으로 나아가, 아무것에도 맞지 않거나 다른 블록 안에 있지 않은 중괄호 닫기 <}-token>를 찾을 때까지 진행합니다. at-규칙의 내용은 해당 at-규칙의 문법에 따라 해석됩니다.
- 한정 규칙도 유사하게 동작하지만, 세미콜론은 끝내지 않고, 규칙의 프렐류드로 받아들입니다. 첫 번째 {} 블록이 발견되면, 그 내용은 항상 선언 목록으로 해석됩니다.
- 선언 목록을 해석할 때, 알 수 없는 구문이 나오면 파서는 현재 작성 중인 선언을 버리고, 세미콜론(또는 블록의 끝)을 찾을 때까지 앞으로 나아갑니다. 그 후 새롭게 선언 파싱을 다시 시도합니다.
- 스타일시트가 끝날 때 규칙, 선언, 함수, 문자열 등이 아직 열려 있으면, 모두 자동으로 닫힙니다. 이로 인해 유효하지 않게 되지는 않지만, 불완전할 수 있으므로 문법 검증 시 버려질 수 있습니다.
각 구성요소(선언, 스타일 규칙, at-규칙) 파싱 후, UA는 예상 문법과 일치하는지 확인합니다. 만약 문법과 일치하지 않으면, 무효가 되어, UA에 의해 무시됩니다. 즉, 존재하지 않는 것과 같이 취급됩니다.
3. CSS 토큰화 및 파싱
UA는 본 명세에서 설명하는 파싱 규칙을 사용하여 text/css 리소스로부터 [CSSOM] 트리를 생성해야 합니다. 이러한 규칙들은 CSS 파서로 불립니다.
이 명세는 CSS 문서의 파싱 규칙을 정의하며, 문법적으로 올바르지 않은 경우도 포함합니다. 파싱 알고리즘의 특정 지점은 파싱 오류라고 합니다. 파싱 오류의 처리 방법은 아래에 명확히 정의되어 있습니다: UA는 이런 문제를 만났을 때 아래에 설명된 대로 동작하거나, 그렇지 않은 경우에는 첫 번째 오류에서 처리를 중단해야 합니다.
적합성 검사기는 문서에 하나 이상의 파싱 오류 조건이 있으면 최소 하나의 오류 조건을 보고해야 하며, 오류 조건이 없으면 보고하지 않아야 합니다. 오류 조건이 여러 개 있으면 여러 개를 보고할 수 있습니다. 적합성 검사기는 파싱 오류로부터 복구할 필요는 없지만, 복구 시 UA와 동일한 방식으로 복구해야 합니다.
3.1. 파싱 모델 개요
CSS 파싱 과정의 입력은 유니코드 코드 포인트 스트림이며, 토큰화 단계와 트리 생성 단계를 거칩니다. 출력은 CSSStyleSheet 객체입니다.
참고: 스크립팅을 지원하지 않는 구현에서는 실제로 CSSOM CSSStyleSheet 객체를 생성할 필요는 없지만, 이런 경우에도 CSSOM 트리는 명세의 나머지 부분에 대한 모델로 사용됩니다.
3.2. 입력 바이트 스트림
스타일시트를 파싱할 때, 토큰화 단계에 입력되는 유니코드 코드 포인트 스트림은 UA에 의해 바이트 스트림(보통 네트워크 또는 파일 시스템을 통해 수신됨)으로 처음 인식될 수 있습니다. 이런 경우 UA는 해당 바이트를 특정 문자 인코딩에 따라 코드 포인트로 디코딩해야 합니다.
-
대체 인코딩 결정을 스타일시트에 대해 수행하고, fallback에 결과를 저장합니다.
-
디코드 스타일시트의 바이트 스트림을 대체 인코딩 fallback으로 디코드하여 결과를 반환합니다.
참고: 디코드 알고리즘은 바이트 순서 표시(BOM)에 우선권을 부여하며, BOM이 없을 때만 대체 인코딩을 사용합니다.
- HTTP 또는 동등한 프로토콜이 스타일시트에 대한 인코딩 라벨(예: Content-Type 헤더의 charset 파라미터)을 제공하는 경우, 인코딩 얻기를 인코딩 라벨로 수행합니다. 실패가 아니라면 해당 값을 반환합니다.
-
그렇지 않으면 스타일시트의 바이트 스트림을 검사합니다.
스트림의 처음 1024 바이트가 다음 16진수 시퀀스로 시작하면
40 63 68 61 72 73 65 74 20 22 XX* 22 3B
여기서 각
XX
바이트는 016~2116 또는 2316~7F16 사이 값입니다. 인코딩 얻기를XX
바이트 시퀀스를 ASCII로 해석한 문자열에 대해 수행합니다.이 바이트 시퀀스의 의미는?
위 바이트 시퀀스를 ASCII로 디코드하면, "
@charset "…";
" 문자열이 되며, "…"은 인코딩 라벨에 해당하는 바이트 시퀀스입니다.반환 값이
utf-16be
또는utf-16le
라면utf-8
을 반환합니다; 그 외 실패가 아니면 해당 값을 반환합니다.인코딩 선언이 utf-16일 때 왜 utf-8을 쓰나요?
인코딩 선언의 바이트는 ASCII로 "
@charset "…";
"를 나타내지만, UTF-16은 ASCII 호환이 아닙니다. 올바르지 않은 바이트를 문서에 직접 입력했거나(䁣桡牳整•utf-16be∻
등), 문서는 실제로 ASCII 호환 인코딩이고 인코딩 선언이 잘못된 경우입니다.어떤 경우든, 기본값을 UTF-8로 사용하는 것이 적절합니다.
또한, 이는 HTML의
<meta charset>
속성 동작과 동일합니다.참고: 인코딩 선언의 구문은 at-규칙 @charset과 유사하지만, 실제로 그런 규칙은 존재하지 않습니다. 인코딩 선언의 작성 규칙은 일반적인 규칙보다 훨씬 더 엄격합니다. CSS에서 유효한 @charset 규칙을 생성할 수 있는 여러 방법(여러 개의 공백, 주석, 작은따옴표 등)은 인코딩 선언이 인식되지 않게 만듭니다. 이런 동작은 인코딩 선언을 최대한 단순하게 하여 올바르게 구현될 가능성을 높입니다.
- 그렇지 않으면 참조 문서가 환경 인코딩을 제공하면 해당 값을 반환합니다.
- 그렇지 않으면
utf-8
을 반환합니다.
UTF-8이 웹의 기본 인코딩이고, 많은 최신 웹 기반 파일 형식이 UTF-8 인코딩을 가정하거나 요구하지만, CSS는 어떤 인코딩이 표준이 될지 확실하지 않을 때 만들어졌으므로 자동으로 UTF-8로 가정할 수 없습니다.
스타일시트 작성자는 반드시 UTF-8로 작성하고,
HTTP 헤더(또는 동등한 방법)로 스타일시트 인코딩을 UTF-8로 선언하거나,
참조 문서에서 인코딩을 UTF-8로 선언해야 합니다.
(HTML에서는 <meta charset=utf-8>
요소를 head에 추가합니다.)
이 두 방법 모두 사용할 수 없다면, 스타일시트 시작 부분에 UTF-8 BOM 또는 아래와 같이 작성해야 합니다.
@charset "utf-8";
바이트로 디코드된 CSS 스타일시트를 참조하는 문서 언어는 각 스타일시트에 대해 환경 인코딩을 정의할 수 있으며, 이는 다른 인코딩 힌트가 없거나 사용할 수 없을 때 대체로 사용됩니다.
환경 인코딩 개념은 이전 콘텐츠와의 호환성을 위해 존재합니다. 새로운 포맷과 새로운 연결 방식은 환경 인코딩을 제공하지 않아야 하며, 명확한 정보가 없을 때 스타일시트의 기본값은 UTF-8이 되어야 합니다.
참고: [HTML]은
<link rel=stylesheet>
환경 인코딩을 정의합니다.
참고: [CSSOM]
은
<xml-stylesheet?>
환경 인코딩을 정의합니다.
참고: [CSS-CASCADE-3]은 @import
환경 인코딩을 정의합니다.
3.3. 입력 스트림 전처리
입력 스트림은 입력 바이트 스트림이 디코딩될 때 푸시된 필터링된 코드 포인트로 구성됩니다.
4. 토큰화
토큰화를 위해 코드 포인트 스트림 input에서 토큰 소비를 반복적으로 수행하여 <EOF-token>에 도달할 때까지 각 반환된 토큰을 스트림에 푸시합니다.
참고: 토큰 소비 알고리즘은 항상 하나의 토큰만 반환하므로, 원하는 경우 파싱 중에 코드 포인트 스트림을 "온디맨드"로 토큰화하는 데 사용할 수도 있습니다.
토큰화 단계의 출력은 다음 토큰들로 구성된 0개 이상의 스트림입니다: <ident-token>, <function-token>, <at-keyword-token>, <hash-token>, <string-token>, <bad-string-token>, <url-token>, <bad-url-token>, <delim-token>, <number-token>, <percentage-token>, <dimension-token>, <whitespace-token>, <CDO-token>, <CDC-token>, <colon-token>, <semicolon-token>, <comma-token>, <[-token>, <]-token>, <(-token>, <)-token>, <{-token>, and <}-token>.
- <ident-token>, <function-token>, <at-keyword-token>, <hash-token>, <string-token>, and <url-token>는 0개 이상의 코드 포인트로 구성된 값을 가집니다. 해시 토큰은 타입 플래그가 "id" 또는 "unrestricted"로 설정됩니다. 특별히 설정하지 않으면 "unrestricted"가 기본값입니다.
- <delim-token>는 단일 코드 포인트로 구성된 값을 가집니다.
- <number-token>, <percentage-token>, <dimension-token>는 숫자 값을 가집니다. <number-token>와 <dimension-token>은 타입 플래그가 "integer" 또는 "number"로 설정됩니다. 특별히 설정하지 않으면 "integer"가 기본값입니다. <dimension-token>은 추가로 1개 이상의 코드 포인트로 구성된 단위를 가집니다.
참고: 해시 토큰의 타입 플래그는 Selectors 구문 [SELECT]에서 사용됩니다. "id" 타입의 해시 토큰만 ID 선택자에 유효합니다.
4.1. 토큰 레일로드 다이어그램
이 섹션은 비규범적입니다.
이 섹션은 토크나이저를 레일로드 다이어그램 형태로 설명합니다. 레일로드 다이어그램은 명시적인 파서보다 더 간결하지만, 정규 표현식보다 읽기 쉬운 경우가 많습니다.
이 다이어그램들은 참고용이며 불완전합니다; "올바른" 토큰의 문법만 설명하며, 오류 처리에 대해서는 설명하지 않습니다. 각 토큰의 구문을 직관적으로 이해하기 쉽게 제공됩니다.
<foo-token>과 같은 이름이 붙은 다이어그램은 토큰을 나타냅니다. 나머지는 다른 다이어그램에서 참조되는 생성식입니다.
- comment
-
- newline
-
- whitespace
-
- hex digit
-
- escape
-
- <whitespace-token>
-
- ws*
-
- <ident-token>
-
- <function-token>
-
- <at-keyword-token>
-
- <hash-token>
-
- <string-token>
-
- <url-token>
-
- <number-token>
-
- <dimension-token>
-
- <percentage-token>
-
- <CDO-token>
-
- <CDC-token>
-
4.2. 정의
이 섹션에서는 토큰화 단계에서 사용되는 여러 용어를 정의합니다.
- next input code point
- 아직 소비되지 않은 code point 중 input stream의 첫 번째 값입니다.
- current input code point
- 마지막으로 소비된 code point입니다.
- reconsume the current input code point
- current input code point를 input stream 맨 앞에 다시 푸시하여, 다음에 next input code point를 소비하라는 지시가 있을 때 대신 current input code point를 재소비하게 합니다.
- EOF code point
- code point의 개념적 값으로, input stream의 끝을 나타냅니다. input stream이 비어 있을 때마다 next input code point는 항상 EOF code point입니다.
- digit
- U+0030 DIGIT ZERO (0)부터 U+0039 DIGIT NINE (9)까지의 code point입니다.
- hex digit
- digit이거나, U+0041 LATIN CAPITAL LETTER A (A)부터 U+0046 LATIN CAPITAL LETTER F (F)까지의 code point, 또는 U+0061 LATIN SMALL LETTER A (a)부터 U+0066 LATIN SMALL LETTER F (f)까지의 code point입니다.
- uppercase letter
- U+0041 LATIN CAPITAL LETTER A (A)부터 U+005A LATIN CAPITAL LETTER Z (Z)까지의 code point입니다.
- lowercase letter
- U+0061 LATIN SMALL LETTER A (a)부터 U+007A LATIN SMALL LETTER Z (z)까지의 code point입니다.
- letter
- uppercase letter 또는 lowercase letter입니다.
- non-ASCII code point
- 값이 U+0080 <control> 이상인 code point입니다.
- ident-start code point
- letter, non-ASCII code point, 또는 U+005F LOW LINE (_)입니다.
- ident code point
- ident-start code point, digit, 또는 U+002D HYPHEN-MINUS (-)입니다.
- non-printable code point
- U+0000 NULL부터 U+0008 BACKSPACE 사이의 code point, U+000B LINE TABULATION, U+000E SHIFT OUT부터 U+001F INFORMATION SEPARATOR ONE 사이의 code point, 또는 U+007F DELETE입니다.
- newline
- U+000A LINE FEED. U+000D CARRIAGE RETURN과 U+000C FORM FEED는 이 정의에 포함되지 않습니다. 전처리 과정에서 U+000A LINE FEED로 변환되기 때문입니다.
- whitespace
- newline, U+0009 CHARACTER TABULATION, 또는 U+0020 SPACE입니다.
- maximum allowed code point
- 유니코드에서 정의된 가장 큰 code point: U+10FFFF입니다.
- ident sequence
-
code
points의 시퀀스로, <ident-token>와 동일한 구문을 가집니다.
참고: <at-keyword-token>에서 "@" 이후 부분, <hash-token> (타입 플래그 "id")에서 "#" 이후 부분, <function-token>에서 "(" 이전 부분, <dimension-token>의 단위 모두 ident sequence입니다.
- representation
-
토큰의 representation은
consume a token 알고리즘을
호출할 때 소비된 input stream의 부분
시퀀스입니다.
일부 알고리즘에서는 입력 텍스트의 미세한 세부 정보를 활용하므로, 토큰을 단순히 "재직렬화"하면 깨질 수 있습니다.
representation은 내부 알고리즘에서만 사용되며, 직접적으로 노출되지 않으므로, 실제 텍스트를 정확히 유지할 필요는 없습니다. 예를 들어, 토큰마다 소스 텍스트의 오프셋을 저장하는 것도 충분합니다.
참고: 특히, representation은 .009가 .009로 작성되었는지 또는 9e-3으로 작성되었는지, 문자가 문자 그대로 작성되었는지 CSS 이스케이프로 작성되었는지 등의 세부 정보를 보존합니다. 전자는 <urange> 생성식을 올바르게 파싱하는 데 필요하며, 후자는 토큰화 추상화가 우연히 노출된 것이지만, 구현 정의를 쉽게 하기 위해 허용됩니다.
토큰이 명세의 토큰화 알고리즘이 아닌 다른 알고리즘에 의해 직접 생성된 경우, representation은 빈 문자열입니다.
4.3. 토크나이저 알고리즘
이 섹션에서 정의한 알고리즘은 code points 스트림을 토큰 스트림으로 변환합니다.
4.3.1. 토큰 소비
이 섹션은 code points 스트림에서 토큰 소비하는 방법을 설명합니다. 항상 단일 토큰을 반환합니다.
주석 소비를 수행합니다.
next input code point를 소비합니다.
- whitespace
- 가능한 많은 whitespace를 소비합니다. <whitespace-token>을 반환합니다.
- U+0022 QUOTATION MARK (")
- 문자열 토큰 소비를 수행하고 반환합니다.
- U+0023 NUMBER SIGN (#)
-
next input
code point가 ident code point이거나 다음
두 input code point가 유효한 이스케이프라면,
다음을 수행합니다:
- <hash-token>을 생성합니다.
- 다음 3 input code point가 ident sequence를 시작하는지 확인에 해당하면, <hash-token>의 type flag를 "id"로 설정합니다.
- ident sequence 소비를 수행하고, <hash-token>의 값에 반환된 문자열을 설정합니다.
- <hash-token>을 반환합니다.
그렇지 않으면, <delim-token>을 반환하고 값은 current input code point로 설정합니다.
- U+0027 APOSTROPHE (')
- 문자열 토큰 소비를 수행하고 반환합니다.
- U+0028 LEFT PARENTHESIS (()
- <(-token>을 반환합니다.
- U+0029 RIGHT PARENTHESIS ())
- <)-token>을 반환합니다.
- U+002B PLUS SIGN (+)
-
input stream이 숫자로 시작하면, current input code point 재소비, 숫자 토큰
소비,
그리고 반환합니다.
그렇지 않으면, <delim-token>을 반환하고 값은 current input code point로 설정합니다.
- U+002C COMMA (,)
- <comma-token>을 반환합니다.
- U+002D HYPHEN-MINUS (-)
-
input stream이 숫자로 시작하면, current input code point 재소비, 숫자 토큰
소비,
그리고 반환합니다.
그렇지 않으면, 다음 2 input code point가 U+002D HYPHEN-MINUS U+003E GREATER-THAN SIGN (->)이면, 이 두 값을 소비하고 <CDC-token>을 반환합니다.
그렇지 않으면, input stream이 ident sequence로 시작이면, current input code point 재소비, ident-like 토큰 소비, 그리고 반환합니다.
그렇지 않으면, <delim-token>을 반환하고 값은 current input code point로 설정합니다.
- U+002E FULL STOP (.)
-
input stream이 숫자로 시작하면, current input code point 재소비, 숫자 토큰
소비,
그리고 반환합니다.
그렇지 않으면, <delim-token>을 반환하고 값은 current input code point로 설정합니다.
- U+003A COLON (:)
- <colon-token>을 반환합니다.
- U+003B SEMICOLON (;)
- <semicolon-token>을 반환합니다.
- U+003C LESS-THAN SIGN (<)
-
다음 3 input
code point가
U+0021 EXCLAMATION MARK
U+002D HYPHEN-MINUS
U+002D HYPHEN-MINUS
(!--)이면,
이 세 값을 소비하고 <CDO-token>을 반환합니다.
그렇지 않으면, <delim-token>을 반환하고 값은 current input code point로 설정합니다.
- U+0040 COMMERCIAL AT (@)
-
다음 3 input
code point가 ident sequence를 시작하면, ident
sequence 소비를 수행하고,
반환된 값을 value로 하는 <at-keyword-token>을 생성하여 반환합니다.
그렇지 않으면, <delim-token>을 반환하고 값은 current input code point로 설정합니다.
- U+005B LEFT SQUARE BRACKET ([)
- <[-token>을 반환합니다.
- U+005C REVERSE SOLIDUS (\)
-
input stream이 유효한 이스케이프로 시작하면, current input code point 재소비, ident-like 토큰 소비,
그리고 반환합니다.
그렇지 않으면, 이는 파싱 오류입니다. <delim-token>을 반환하고 값은 current input code point로 설정합니다.
- U+005D RIGHT SQUARE BRACKET (])
- <]-token>을 반환합니다.
- U+007B LEFT CURLY BRACKET ({)
- <{-token>을 반환합니다.
- U+007D RIGHT CURLY BRACKET (})
- <}-token>을 반환합니다.
- digit
- current input code point 재소비, 숫자 토큰 소비, 그리고 반환합니다.
- ident-start code point
- current input code point 재소비, ident-like 토큰 소비, 그리고 반환합니다.
- EOF
- <EOF-token>을 반환합니다.
- anything else
- <delim-token>을 반환하고 값은 current input code point로 설정합니다.
4.3.2. 주석 소비
이 섹션은 주석 소비를 code points 스트림에서 수행하는 방법을 설명합니다. 반환값은 없습니다.
다음 두 input code point가 U+002F SOLIDUS (/)와 U+002A ASTERISK (*)이면, 이 둘과 그 뒤에 오는 code points를 첫 번째 U+002A ASTERISK (*)와 그 다음에 오는 U+002F SOLIDUS (/), 또는 EOF code point까지 모두 소비합니다. 그리고 이 단계의 처음으로 돌아갑니다.
위 문단이 EOF code point를 소비하면서 끝났다면, 이는 파싱 오류입니다.
아무것도 반환하지 않습니다.
4.3.3. 숫자 토큰 소비
이 섹션은 숫자 토큰 소비를 code points 스트림에서 어떻게 수행하는지 설명합니다. 반환값은 <number-token>, <percentage-token>, 또는 <dimension-token>입니다.
숫자 소비를 수행하여 number에 결과를 저장합니다.
다음 3 input code points가 ident sequence를 시작하는지 확인에 해당하면,
- number와 동일한 값 및 타입 플래그를 가진 <dimension-token>을 생성하고, 단위는 빈 문자열로 초기화합니다.
- ident sequence 소비를 수행합니다. 반환값을 <dimension-token>의 단위로 설정합니다.
- <dimension-token>을 반환합니다.
그렇지 않고, 다음 input code point가 U+0025 PERCENTAGE SIGN (%)라면, 이를 소비합니다. number와 동일한 값을 가진 <percentage-token>을 생성하여 반환합니다.
그 밖의 경우, number와 동일한 값 및 타입 플래그를 가진 <number-token>을 생성하여 반환합니다.
4.3.4. 식별자 유사 토큰 소비
이 섹션은 식별자 유사 토큰 소비를 code points 스트림에서 어떻게 수행하는지 설명합니다. 반환값은 <ident-token>, <function-token>, <url-token>, 또는 <bad-url-token>입니다.
ident sequence 소비를 수행하고, string에 결과를 저장합니다.
string의 값이 "url"과 ASCII 대소문자 구분 없이 일치하고, 다음 input code point가 U+0028 LEFT PARENTHESIS (()라면, 이를 소비합니다. 다음 두 input code point가 whitespace인 동안, 다음 input code point를 소비합니다. 다음 한 개 또는 두 개 input code point가 U+0022 QUOTATION MARK ("), U+0027 APOSTROPHE ('), 또는 whitespace 뒤에 U+0022 QUOTATION MARK (")나 U+0027 APOSTROPHE (')이면, string 값을 가진 <function-token>을 생성하여 반환합니다. 그렇지 않으면, url 토큰 소비를 수행하고 반환합니다.
그 밖의 경우, 다음 input code point가 U+0028 LEFT PARENTHESIS (()이면, 이를 소비합니다. string 값을 가진 <function-token>을 생성하여 반환합니다.
그 밖의 경우, string 값을 가진 <ident-token>을 생성하여 반환합니다.
4.3.5. 문자열 토큰 소비
이 섹션은 문자열 토큰 소비를 code points 스트림에서 수행하는 방법을 설명합니다. 반환값은 <string-token> 또는 <bad-string-token>입니다.
이 알고리즘은 ending code point와 함께 호출될 수 있으며, 문자열을 끝내는 code point를 나타냅니다. ending code point가 지정되지 않으면, current input code point가 사용됩니다.
초기에는 값이 빈 문자열인 <string-token>을 생성합니다.
스트림에서 next input code point를 반복적으로 소비합니다:
- ending code point
- <string-token>을 반환합니다.
- EOF
- 파싱 오류입니다. <string-token>을 반환합니다.
- newline
- 파싱 오류입니다. current input code point 재소비, <bad-string-token>을 생성하여 반환합니다.
- U+005C REVERSE SOLIDUS (\)
-
다음 input code
point가 EOF이면,
아무것도 하지 않습니다.
그 밖의 경우, 다음 input code point가 newline이면, 이를 소비합니다.
그 밖의 경우, (스트림이 유효한 이스케이프로 시작하는 경우) 이스케이프된 코드 포인트 소비를 수행하고 반환된 code point를 <string-token>의 값에 추가합니다.
- anything else
- current input code point를 <string-token>의 값에 추가합니다.
4.3.6. URL 토큰 소비
이 섹션은 URL 토큰 소비를 code points 스트림에서 수행하는 방법을 설명합니다. 반환값은 <url-token> 또는 <bad-url-token>입니다.
참고: 이 알고리즘은 초기 "url("이 이미 소비된 상태를 가정합니다. 또한 "url(foo)"처럼 따옴표가 없는 값을 소비하기 위해 호출되는 것을 가정합니다. 따옴표가 있는 값(예: url("foo"))은 <function-token>으로 파싱됩니다. 식별자 유사 토큰 소비는 이 구분을 자동으로 처리하며, 이 알고리즘을 직접 호출해서는 안 됩니다.
- 값이 빈 문자열인 <url-token>을 생성합니다.
- 가능한 많은 whitespace를 소비합니다.
-
스트림에서 next
input code point를 반복적으로 소비합니다:
- U+0029 RIGHT PARENTHESIS ())
- <url-token>을 반환합니다.
- EOF
- 파싱 오류입니다. <url-token>을 반환합니다.
- whitespace
- 가능한 많은 whitespace를 소비하세요. next input code point가 U+0029 오른쪽 괄호 ()) 또는 EOF라면, 그것을 소비하고 <url-token>을 반환하세요(EOF가 발생하면 파싱 오류입니다); 그렇지 않으면, 잘못된 url의 나머지를 소비하고, <bad-url-token>을 생성하여 반환하세요.
- U+0022 QUOTATION MARK (")
- U+0027 APOSTROPHE (')
- U+0028 LEFT PARENTHESIS (()
- non-printable code point
- U+0027 APOSTROPHE (')
- 파싱 오류입니다. 잘못된 URL의 나머지 소비를 수행하고, <bad-url-token>을 생성하여 반환합니다.
- U+005C REVERSE SOLIDUS (\)
-
스트림이 유효한 이스케이프로 시작하면, 이스케이프된 코드 포인트 소비를 수행하고
반환된 code point를 <url-token>의 값에 추가합니다.
그 밖의 경우, 파싱 오류입니다. 잘못된 URL의 나머지 소비를 수행하고, <bad-url-token>을 생성하여 반환합니다.
- anything else
- current input code point를 <url-token>의 값에 추가합니다.
4.3.7. 이스케이프된 코드 포인트 소비
이 섹션은 이스케이프된 코드 포인트 소비 방법을 설명합니다. U+005C REVERSE SOLIDUS (\)가 이미 소비된 상태이며, 다음 input code point가 유효한 이스케이프의 일부임을 확인한 상태임을 가정합니다. 반환값은 code point입니다.
next input code point를 소비합니다.
- hex digit
- 가능한 많은 hex digits를 소비하지만 최대 5개까지만 소비합니다. 즉, 총 1~6개의 hex digit이 소비됩니다. next input code point가 whitespace이면, 이것도 소비합니다. hex digits를 16진수 숫자로 해석합니다. 이 숫자가 0이거나, surrogate에 해당하거나, 최대 허용 코드 포인트보다 크면, U+FFFD 대체 문자(�)를 반환합니다. 그렇지 않으면 그 값의 code point를 반환합니다.
- EOF
- 파싱 오류입니다. U+FFFD 대체 문자(�)를 반환합니다.
- anything else
- current input code point를 반환합니다.
4.3.8. 두 코드 포인트가 유효한 이스케이프인지 확인
이 섹션은 두 코드 포인트가 유효한 이스케이프인지 확인 방법을 설명합니다. 여기서 설명된 알고리즘은 두 개의 code points로 명시적으로 호출할 수 있고, 또는 input stream 자체로 호출할 수 있습니다. 후자의 경우, 해당하는 두 code points는 current input code point와 next input code point입니다.
참고: 이 알고리즘은 추가적인 code point를 소비하지 않습니다.
첫 번째 code point가 U+005C REVERSE SOLIDUS (\)가 아니면, false를 반환합니다.
그 밖의 경우, 두 번째 code point가 newline이면, false를 반환합니다.
그 밖의 경우, true를 반환합니다.
4.3.9. 세 코드 포인트가 식별자 시퀀스를 시작하는지 확인
이 섹션에서는 세 개의 코드 포인트가 ident 시퀀스의 시작이 되는지 확인하는 방법을 설명합니다. 여기에 설명된 알고리즘은 세 개의 코드 포인트를 명시적으로 전달하여 호출할 수도 있고, 입력 스트림 자체를 전달하여 호출할 수도 있습니다. 후자의 경우, 문제의 세 코드 포인트는 현재 입력 코드 포인트와 다음 두 입력 코드 포인트이며, 이 순서대로 처리됩니다.
참고: 이 알고리즘은 추가적인 code points를 소비하지 않습니다.
첫 번째 code point를 확인하세요:
- U+002D HYPHEN-MINUS
- 두 번째 code point가 ident-start code point 또는 U+002D HYPHEN-MINUS이거나, 두 번째와 세 번째 code points가 유효한 이스케이프라면, true를 반환합니다. 그렇지 않으면 false를 반환합니다.
- ident-start code point
- true를 반환합니다.
- U+005C REVERSE SOLIDUS (\)
- 첫 번째와 두 번째 code points가 유효한 이스케이프라면, true를 반환합니다. 그렇지 않으면 false를 반환합니다.
- anything else
- false를 반환합니다.
4.3.10. 세 코드 포인트가 숫자를 시작하는지 확인
이 섹션은 세 코드 포인트가 숫자를 시작하는지 확인 방법을 설명합니다. 여기서 설명된 알고리즘은 세 개의 code points로 명시적으로 호출할 수 있고, 또는 input stream 자체로 호출할 수 있습니다. 후자의 경우, 해당하는 세 code points는 current input code point와 next two input code points입니다.
참고: 이 알고리즘은 추가적인 code point를 소비하지 않습니다.
첫 번째 code point를 확인하세요:
- U+002B PLUS SIGN (+)
- U+002D HYPHEN-MINUS (-)
-
두 번째 code point가 digit이면,
true를 반환합니다.
그렇지 않으면, 두 번째 code point가 U+002E FULL STOP (.) 그리고 세 번째 code point가 digit이면, true를 반환합니다.
그 외에는 false를 반환합니다.
- U+002E FULL STOP (.)
- 두 번째 code point가 digit이면, true를 반환합니다. 아니면 false를 반환합니다.
- digit
- true를 반환합니다.
- anything else
- false를 반환합니다.
4.3.11. 식별자 시퀀스 소비
이 섹션은 식별자 시퀀스 소비를 code points 스트림에서 수행하는 방법을 설명합니다. 반환값은 스트림의 첫 번째 code points부터 인접한 최대 이름을 담은 문자열입니다.
참고: 이 알고리즘은 반환된 code points가 <ident-token>을 구성하는지 확인하는 첫 몇 개 code points의 검증을 수행하지 않습니다. 만약 그 용도라면, 이 알고리즘을 호출하기 전에 스트림이 ident sequence로 시작하는지 확인하세요.
result를 빈 문자열로 초기화하세요.
스트림에서 next input code point를 반복적으로 소비하세요:
- ident code point
- code point를 result에 추가합니다.
- 스트림이 유효한 이스케이프로 시작하면
- 이스케이프된 코드 포인트 소비를 수행합니다. 반환된 code point를 result에 추가합니다.
- anything else
- current input code point 재소비. result를 반환합니다.
4.3.12. 숫자 소비
이 섹션은 숫자 소비를 code points 스트림에서 수행하는 방법을 설명합니다. 반환값은 숫자 value와, "integer" 또는 "number"인 type입니다.
참고: 이 알고리즘은 스트림에서 숫자를 얻을 수 있는지 확인하는 첫 몇 개 code points의 검증을 수행하지 않습니다. 이 알고리즘을 호출하기 전에 스트림이 숫자로 시작하는지 확인하세요.
다음 단계를 순서대로 수행하세요:
- type을 "integer"로 초기화합니다. repr을 빈 문자열로 설정합니다.
- next input code point가 U+002B PLUS SIGN (+) 또는 U+002D HYPHEN-MINUS (-)이면, 이를 소비하고 repr에 추가합니다.
- next input code point가 digit인 동안, 이를 소비하고 repr에 추가합니다.
-
다음 2 input
code points가
U+002E FULL STOP (.)와 digit이면,
- 이 둘을 소비합니다.
- 이 둘을 repr에 추가합니다.
- type을 "number"로 설정합니다.
- next input code point가 digit인 동안, 소비하고 repr에 추가합니다.
-
다음 2 또는 3
input code points가
U+0045 LATIN CAPITAL LETTER E (E) 또는 U+0065 LATIN SMALL LETTER E (e),
선택적으로 U+002D HYPHEN-MINUS (-) 또는 U+002B PLUS SIGN (+),
그리고 digit이면,
- 이들을 소비합니다.
- 이들을 repr에 추가합니다.
- type을 "number"로 설정합니다.
- next input code point가 digit인 동안, 소비하고 repr에 추가합니다.
- repr을 숫자로 변환하고, 반환된 값을 value에 설정합니다.
- value와 type을 반환합니다.
4.3.13. 문자열을 숫자로 변환
이 섹션은 문자열을 숫자로 변환하는 방법을 설명합니다. 반환값은 숫자입니다.
참고: 이 알고리즘은 문자열이 숫자만 포함하는지 확인하지 않습니다. 호출 전에 문자열이 올바른 CSS 숫자만 포함하는지 확인하세요.
문자열을 왼쪽에서 오른쪽 순서로 7개 부분으로 나눕니다:
- 부호: 단일 U+002B PLUS SIGN (+) 또는 U+002D HYPHEN-MINUS (-), 또는 빈 문자열. 부호가 U+002D HYPHEN-MINUS (-)면 s를 -1로; 그렇지 않으면 s를 1로 합니다.
- 정수 부분: 0개 이상의 digit. digit이 하나 이상 있으면, digit을 10진수로 해석한 값이 i가 되고; 없으면 i를 0으로 합니다.
- 소수점: 단일 U+002E FULL STOP (.), 또는 빈 문자열.
- 소수 부분: 0개 이상의 digit. digit이 하나 이상 있으면, digit을 10진수로 해석한 값을 f로 하고, digit의 개수를 d로 합니다; 없으면 f와 d를 0으로 합니다.
- 지수 표시: 단일 U+0045 LATIN CAPITAL LETTER E (E) 또는 U+0065 LATIN SMALL LETTER E (e), 또는 빈 문자열.
- 지수 부호: 단일 U+002B PLUS SIGN (+) 또는 U+002D HYPHEN-MINUS (-), 또는 빈 문자열. 부호가 U+002D HYPHEN-MINUS (-)면 t를 -1로; 그렇지 않으면 t를 1로 합니다.
- 지수: 0개 이상의 digit. digit이 하나 이상 있으면, digit을 10진수로 해석한 값이 e가 되고; 없으면 e를 0으로 합니다.
다음 숫자 s·(i + f·10-d)·10te
를 반환합니다.
4.3.14. 잘못된 URL의 나머지 소비
이 섹션은 잘못된 URL의 나머지 소비를 code points 스트림에서 수행하는 방법을 설명합니다. 이는 토크나이저가 <bad-url-token>의 중간임을 인식했을 때 "정리"를 수행하기 위한 것으로, 반환값은 없습니다; 오직 정상 토큰화로 복귀할 수 있는 회복 지점에 도달할 때까지 입력 스트림을 충분히 소비하는 데에만 사용됩니다.
스트림에서 next input code point를 반복적으로 소비하세요:
- U+0029 RIGHT PARENTHESIS ())
- EOF
- 반환합니다.
- 입력 스트림이 유효한 이스케이프로 시작하면
- 이스케이프된 코드 포인트 소비를 수행합니다. 이는 이스케이프된 우괄호("\)")가 <bad-url-token>를 끝내지 않도록 허용합니다. 이외의 경우는 "anything else"와 동일합니다.
- anything else
- 아무것도 하지 않습니다.
5. 파싱
파싱 단계의 입력은 토큰화 단계에서 나온 토큰 스트림 또는 목록입니다. 출력은 이 섹션 뒤쪽에 나열된 진입점에 따라 파서가 어떻게 호출되는지에 따라 달라집니다. 파서의 출력에는 at-규칙, 한정 규칙, 선언이 포함될 수 있습니다.
파서의 출력은 CSS의 기본 구문에 따라 생성되며, 특정 항목의 유효성은 고려하지 않습니다. 구현체는 다양한 파서 알고리즘에서 항목이 반환될 때마다 해당 항목의 유효성을 검사하고, 구현체 자체의 문법 지식에 따라 항목이 무효이면 아무것도 반환하지 않는 것으로 처리하거나, 명세대로 전체 트리를 생성한 뒤에 무효 항목을 제거하는 방식으로 "정리"할 수 있습니다.
트리에 들어갈 수 있는 항목은 다음과 같습니다:
- at-규칙
-
at-규칙은 이름,
컴포넌트 값 목록으로 구성된 프렐류드,
그리고 선택적으로 단순 {} 블록으로 구성된 블록을 가집니다.
참고: 본 명세는 at-규칙 블록의 내용에 제한을 두지 않습니다. 개별 at-규칙에서 블록을 허용할지 여부와, 허용한다면 블록을 어떻게 파싱할지 (가능하면 본 명세에서 정의한 파서 알고리즘이나 진입점을 사용하는 방식으로) 정의해야 합니다.
- 한정 규칙
-
한정 규칙은
컴포넌트 값 목록으로 구성된 프렐류드와,
단순 {} 블록으로 구성된 블록을 가집니다.
참고: 대부분의 한정 규칙은 스타일 규칙이며, 프렐류드는 선택자 [SELECT]이고, 블록은 선언 목록입니다.
- 선언
-
개념적으로 선언은 속성이나 디스크립터 이름을 값과 연결하는 특정 인스턴스입니다.
문법적으로 선언은 이름,
컴포넌트 값 목록으로 구성된 값,
그리고 초기화되지 않은 important 플래그를 가집니다.
선언은 더 세분화되어 속성 선언 또는 디스크립터 선언으로 구분되며, 전자는 CSS 속성을 설정하고 대부분 한정 규칙에 나타나며, 후자는 CSS 디스크립터를 설정하며, 이는 오직 at-규칙에만 나타납니다. (이 분류는 구문 레벨에서는 일어나지 않으며, 선언이 나타나는 위치에 따라 결정되며, 해당 규칙을 정의하는 각각의 명세에서 정의됩니다.)
- 컴포넌트 값
- 컴포넌트 값은 보존 토큰, 함수, 또는 단순 블록입니다.
- 보존 토큰
-
토크나이저가 생성한 모든 토큰
단, <function-token>, <{-token>, <(-token>,
그리고 <[-token>는 제외합니다.
참고: 위에서 나열된 비-preserved tokens들은 항상 더 상위 객체(함수 또는 단순 블록)로 소비되기 때문에, 파서 출력에 직접적으로 나타나지 않습니다.
참고: <}-token>, <)-token>, <]-token>, <bad-string-token>, <bad-url-token> 등의 토큰은 항상 파싱 오류입니다. 하지만 이 명세에서는 토큰 스트림에 보존하여 Media Queries와 같은 다른 명세가 전체 선언이나 블록을 버리는 것 이상의 더 세밀한 오류 처리를 정의할 수 있도록 합니다.
- 함수
- 함수는 이름과 컴포넌트 값 목록으로 구성된 값을 가집니다.
- 단순
블록
- {}-블록
- []-블록
- ()-블록
- {}-블록
- 단순 블록은 연관된 토큰(<[-token>, <(-token>, 또는 <{-token>)과 컴포넌트 값 목록으로 구성된 값을 가집니다.
5.1. 파서 레일로드 다이어그램
이 섹션은 비규범적입니다.
이 섹션은 파서를 레일로드 다이어그램 형태로 설명합니다.
이 다이어그램들은 참고용이며 불완전합니다; "올바른" 스타일시트의 문법만 설명하며, 오류 처리에 대해서는 설명하지 않습니다. 구문의 직관적 이해를 돕기 위해 제공됩니다.
- Stylesheet
-
- Rule list
-
- At-rule
-
- Qualified rule
-
- Declaration list
-
- Declaration
-
- !important
-
- Component value
-
- {} block
-
- () block
-
- [] block
-
- Function block
-
5.2. 정의
- current input token
- 토크나이저가 생성한 토큰 목록에서 현재 처리 중인 토큰 또는 component value입니다.
- next input token
- 토크나이저가 생성한 토큰 목록에서 current input token 다음에 오는 토큰 또는 component value입니다. current input token 뒤에 토큰이 없으면, next input token은 <EOF-token>입니다.
- <EOF-token>
- 토큰 목록의 끝을 나타내는 개념적 토큰입니다. 토큰 목록이 비어 있을 때마다, next input token은 항상 <EOF-token>입니다.
- consume the next input token
- current input token을 현재 next input token으로 지정하고, next input token을 그에 따라 조정합니다.
- reconsume the current input token
- 다음에 알고리즘에서 consume the next input token을 하라는 지시가 있을 때, 아무 것도 하지 않고 (current input token을 그대로 유지).
5.3. 파서 진입점
이 섹션에서 정의된 알고리즘은 CSS 토큰 목록에서 고수준 CSS 객체를 생성합니다.
주어진 input을 토큰 스트림으로 정규화하려면:
-
input이 CSS 토큰 목록이면, input을 반환합니다.
-
input이 CSS component value 목록이면, input을 반환합니다.
참고: 토큰 목록과 component value 목록의 차이는, 함수나 블록처럼 무언가를 "포함하는" 객체가 component-value 목록에서는 단일 엔티티이지만, 토큰 목록에서는 여러 엔티티라는 점입니다. 이는 이 명세의 어떤 알고리즘에도 아무런 차이를 주지 않습니다.
-
input이 string이면, input에서 코드 포인트 필터링을 하고, 토큰화한 결과를 반환합니다.
-
단언: 위의 타입만 input에 전달되어야 합니다.
참고: 다른 명세에서 자체 목적을 위해 추가 진입점을 정의할 수 있습니다.
- "스타일시트 파싱"는 스타일시트 파싱을 위한 일반적인 파서 진입점으로 사용됩니다.
- "규칙 목록 파싱"은 @media 같은 at-규칙의 내용에 사용됩니다. 이것은 "스타일시트 파싱"과 <CDO-token> 및 <CDC-token> 처리 방식이 다릅니다.
- "규칙 파싱"는
CSSStyleSheet#insertRule
메서드 및 유사한 함수에서 텍스트를 단일 규칙으로 파싱할 때 사용됩니다. - "선언 파싱"는 @supports 조건에서 사용됩니다. [CSS3-CONDITIONAL]
- "선언 목록 파싱"는
style
속성의 내용에 사용되며, 텍스트를 단일 스타일 규칙의 내용으로 파싱합니다. - "컴포넌트 값 파싱"는 attr() 등의 규칙에서 단일 값을 소비해야 할 때 사용됩니다.
- "컴포넌트 값 목록 파싱"는 표현 속성의 내용,
단일 선언 값으로 텍스트를 파싱하거나, 독립 선택자 [SELECT]
또는 Media Query 목록 [MEDIAQ] 파싱 시 사용됩니다.
예: Selectors API 또는
media
HTML 속성.
5.3.1. CSS 문법에 따라 파싱
문자열이나 토큰 목록이 어떤 CSS 문법과 일치하는지 파싱/검증하고, 일치할 경우 그 문법에 따라 구조를 분해하는 것이 종종 필요합니다. 이 섹션은 그런 작업을 위한 일반적인 훅을 제공합니다. "parse foo as a CSS <color>" 등으로 호출합니다.
이 알고리즘은 입력이 주어진 문법에 맞지 않으면 failure를 반환하며, 맞으면 해당 문법에 따라 입력을 파싱한 결과(해당 문법 스펙에 대응하는 미정의 구조)를 반환합니다. 반환값은 명세 서술에서만 사용되어야 하며, 표현의 모호성이 문제가 되지 않습니다. 명세 외에 노출할 목적이라면, 결과를 명확하게 정의된 표현으로 변환(예: CSS 직렬화 알고리즘 호출 ("serialize as a CSS <string> value") 등)해야 합니다.
참고: 이 알고리즘과 CSS 문법에 따라 쉼표로 구분된 목록 파싱은 대부분 다른 명세에서 호출하고 싶은 파싱 알고리즘입니다. 나머지 파싱 알고리즘은 주로 [CSSOM] 및 "CSS 구조를 명시적으로 생성"하는 경우에 사용됩니다. 다른 알고리즘이 필요하다면 CSSWG에 먼저 문의하세요.
- 정규화 input, 그 결과를 input에 설정.
- 컴포넌트 값 목록 파싱을 input에서 수행, 반환값을 result에 저장.
- result가 grammar와 일치하는지 시도. 성공하면 일치 결과를 반환; 아니면 failure를 반환.
5.3.2. CSS 문법에 따라 쉼표로 구분된 목록 파싱
값에 쉼표가 있는 문법으로 파싱할 수 있지만, 값의 어느 한 부분이라도 파싱에 실패하면 전체가 파싱 실패(failure)를 반환합니다.
이런 동작이 필요한 경우도 있지만(예: 목록 값을 가지는 CSS 속성),
다른 경우엔 값의 쉼표로 구분된 각 부분을 개별적으로 파싱하고,
성공한 부분과 실패한 부분을 각각 다르게 처리하는 것이 더 낫습니다
(실패한 부분은 무시—예:
<img sizes>
).
이 알고리즘은 그런 동작을 쉽게 구현할 수 있도록 합니다. "최상위" 쉼표로 분리된 값 리스트를 반환하며, 각 값은 실패(failure) (파싱에 실패한 경우) 또는 파싱 결과(미정의 구조, 위 파싱 알고리즘 참조)입니다.
- 정규화 input, 그 결과를 input에 설정.
- input이 <whitespace-token>만 포함하면, 빈 리스트를 반환.
- 컴포넌트 값 쉼표 목록 파싱을 input에서 수행, 반환값을 list에 저장.
- 각 item에 대해, item을 파싱하여 grammar와 함께 결과로 대체.
- list를 반환.
5.3.3. 스타일시트 파싱
5.3.4. 규칙 목록 파싱
5.3.5. 규칙 파싱
- 정규화 input, 그 결과를 input에 설정.
- input에서 next input token이 <whitespace-token>인 동안, consume the next input token을 input에서 수행.
-
input에서 next input token이 <EOF-token>이면,
구문 오류(syntax error) 반환.
그 밖의 경우, input에서 next input token이 <at-keyword-token>이면, at-규칙 소비를 input에서 수행, 반환값을 rule에 저장.
그 밖의 경우, 한정 규칙 소비를 input에서 수행, 반환값을 rule에 저장. 값이 없으면 구문 오류 반환.
- input에서 next input token이 <whitespace-token>인 동안, consume the next input token을 input에서 수행.
- input에서 next input token이 <EOF-token>이면, rule을 반환. 그렇지 않으면 구문 오류 반환.
5.3.6. 선언 파싱
참고: "선언 목록 파싱"과 달리, 이 알고리즘은 선언만 파싱하며 at-규칙은 파싱하지 않습니다.
- 정규화 input, 그 결과를 input에 설정.
- input에서 next input token이 <whitespace-token>인 동안, consume the next input token을 수행.
- input에서 next input token이 <ident-token>이 아니면, 구문 오류 반환.
- 선언 소비를 input에서 수행. 값이 반환되면 그 값을 반환; 아니면 구문 오류 반환.
5.3.7. 스타일 블록 내용 파싱
참고: 이 알고리즘은 스타일 규칙의 내용을 파싱하며, 중첩 스타일 규칙과 기타 at-규칙을 허용해야 합니다. 중첩 스타일 규칙이 필요하지 않다면, 예를 들어 @page나 @keyframes 자식 규칙처럼, 선언 목록 파싱을 사용하세요.
- 정규화 input, 결과를 input에 저장합니다.
- 스타일 블록 내용 소비를 input에서 수행하고, 결과를 반환합니다.
5.3.8. 선언 목록 파싱
참고: 이름과는 달리, 실제로는 선언과 at-규칙이 혼합된 목록을 파싱하며, CSS 2.1의 @page에 해당합니다. 예상치 못한 at-규칙(특정 문맥에서는 모든 at-규칙일 수 있음)은 무효이며 소비자에 의해 무시됩니다.
참고: 이 알고리즘은 중첩된 스타일 규칙을 처리하지 않습니다. 그게 필요하다면, 스타일 블록 내용 파싱을 사용하세요.
5.3.9. 컴포넌트 값 파싱
- 정규화 input, 결과를 input에 저장합니다.
- input에서 next input token이 <whitespace-token>인 동안, consume the next input token을 수행합니다.
- input에서 next input token이 <EOF-token>이면, 구문 오류를 반환합니다.
- 컴포넌트 값 소비를 input에서 수행하고, 반환값을 value에 저장합니다.
- input에서 next input token이 <whitespace-token>인 동안, consume the next input token을 수행합니다.
- input에서 next input token이 <EOF-token>이면, value를 반환합니다. 그렇지 않으면, 구문 오류를 반환합니다.
5.3.10. 컴포넌트 값 목록 파싱
- input을 정규화하고, input을 그 결과로 설정합니다.
- input에서 컴포넌트 값 소비를 반복적으로 수행하여 <EOF-token>이 반환될 때까지, 반환된 값(마지막 <EOF-token> 제외)을 리스트에 추가합니다. 리스트를 반환합니다.
5.3.11. 컴포넌트 값 쉼표 목록 파싱
- 정규화 input, 결과를 input에 저장합니다.
- list of cvls를 초기 빈 컴포넌트 값 목록 리스트로 설정합니다.
-
컴포넌트 값 소비를 input에서 <EOF-token> 또는 <comma-token>이 반환될 때까지 반복적으로 수행하며,
반환값(마지막 <EOF-token> 또는 <comma-token> 제외)을 리스트에 추가합니다.
리스트를 list of cvls에 추가합니다.
만약 <comma-token>이 반환되었다면, 이 단계를 반복합니다.
- list of cvls를 반환합니다.
5.4. 파서 알고리즘
다음 알고리즘들은 파서를 구성합니다. 이들은 위의 파서 진입점에서 호출됩니다.
이 알고리즘들은 토큰 목록 또는 컴포넌트 값 목록을 받을 수 있습니다. (차이점은 컴포넌트 값 목록에서는 일부 토큰이 함수 또는 단순 블록으로 대체된다는 것입니다.) 토큰화 단계에서 입력 스트림이 비어 있을 때 EOF 코드 포인트를 반환했던 것처럼, 이 단계의 목록들도 비어 있을 때 다음 토큰을 요청하면 <EOF-token>을 반환해야 합니다.
알고리즘은 특정 리스트와 함께 호출될 수 있으며, 그 경우 해당 리스트만 소비합니다 (리스트가 소진되면, <EOF-token>을 반환하기 시작합니다.) 그렇지 않으면, 암묵적으로 호출하는 알고리즘과 동일한 리스트를 사용합니다.
5.4.1. 규칙 목록 소비
규칙 목록 소비를 top-level flag와 함께 수행하려면:
초기 빈 규칙 리스트를 생성합니다.
next input token을 반복적으로 소비하세요:
- <whitespace-token>
- 아무것도 하지 않습니다.
- <EOF-token>
- 규칙 리스트를 반환합니다.
- <CDO-token>
- <CDC-token>
-
top-level flag가 설정되어 있으면,
아무것도 하지 않습니다.
그 밖의 경우, current input token 재소비. 한정 규칙 소비. 값이 반환되면, 규칙 리스트에 추가합니다.
- <at-keyword-token>
- current input token 재소비. at-규칙 소비, 반환값을 규칙 리스트에 추가합니다.
- anything else
- current input token 재소비. 한정 규칙 소비. 값이 반환되면, 규칙 리스트에 추가합니다.
5.4.2. at-규칙 소비
at-규칙 소비를 수행하려면:
consume the next input token을 수행합니다. 새 at-규칙을 생성하고 이름을 current input token의 값으로 설정, 프렐류드는 초기 빈 리스트로, 값은 아무것도 없는 상태로 설정합니다.
next input token을 반복적으로 소비하세요:
- <semicolon-token>
- at-규칙을 반환합니다.
- <EOF-token>
- 파싱 오류입니다. at-규칙을 반환합니다.
- <{-token>
- 단순 블록 소비를 수행하여 at-규칙의 블록에 할당합니다. at-규칙을 반환합니다.
- 단순 블록의 연관 토큰이 <{-token>인 경우
- 블록을 at-규칙의 블록에 할당합니다. at-규칙을 반환합니다.
- anything else
- current input token 재소비. 컴포넌트 값 소비를 수행합니다. 반환값을 at-규칙 프렐류드에 추가합니다.
5.4.3. 한정 규칙 소비
한정 규칙 소비를 수행하려면:
새 한정 규칙을 생성하고 프렐류드는 초기 빈 리스트로, 값은 아무것도 없는 상태로 설정합니다.
next input token을 반복적으로 소비하세요:
- <EOF-token>
- 파싱 오류입니다. 아무것도 반환하지 않습니다.
- <{-token>
- 단순 블록 소비를 수행하여 한정 규칙의 블록에 할당합니다. 한정 규칙을 반환합니다.
- 단순 블록의 연관 토큰이 <{-token>인 경우
- 블록을 한정 규칙의 블록에 할당합니다. 한정 규칙을 반환합니다.
- anything else
- current input token 재소비. 컴포넌트 값 소비를 수행합니다. 반환값을 한정 규칙 프렐류드에 추가합니다.
5.4.4. 스타일 블록 내용 소비
스타일 블록 내용 소비를 수행하려면:
초기 빈 선언 리스트 decls와 초기 빈 규칙 리스트 rules를 생성합니다.
next input token을 반복적으로 소비하세요:
- <whitespace-token>
- <semicolon-token>
- 아무것도 하지 않습니다.
- <EOF-token>
- decls를 rules로 확장한 뒤, decls를 반환합니다.
- <at-keyword-token>
- current input token 재소비. at-규칙 소비를 수행하고, 결과를 rules에 추가합니다.
- <ident-token>
- 임시 리스트를 초기화하고 current input token으로 채웁니다. next input token이 <semicolon-token> 또는 <EOF-token>이 아닌 동안, 컴포넌트 값 소비를 수행하여 임시 리스트에 추가합니다. 선언 소비를 임시 리스트에서 수행합니다. 값이 반환되면, decls에 추가합니다.
- <delim-token>의 값이 "&" (U+0026 AMPERSAND)인 경우
- current input token 재소비. 한정 규칙 소비. 값이 반환되면, rules에 추가합니다.
- anything else
- 파싱 오류입니다. current input token 재소비. next input token이 <semicolon-token> 또는 <EOF-token>이 아닌 동안, 컴포넌트 값 소비를 수행하고 반환값은 버립니다.
5.4.5. 선언 목록 소비
선언 목록 소비를 수행하려면:
초기 빈 선언 리스트를 생성합니다.
next input token을 반복적으로 소비하세요:
- <whitespace-token>
- <semicolon-token>
- 아무것도 하지 않습니다.
- <EOF-token>
- 선언 리스트를 반환합니다.
- <at-keyword-token>
- current input token 재소비. at-규칙 소비. 반환된 규칙을 선언 리스트에 추가합니다.
- <ident-token>
- 임시 리스트를 초기화하고 current input token으로 채웁니다. next input token이 <semicolon-token> 또는 <EOF-token>이 아닌 동안, 컴포넌트 값 소비를 수행하여 임시 리스트에 추가합니다. 선언 소비를 임시 리스트에서 수행합니다. 값이 반환되면, 선언 리스트에 추가합니다.
- anything else
- 파싱 오류입니다. current input token 재소비. next input token이 <semicolon-token> 또는 <EOF-token>이 아닌 동안, 컴포넌트 값 소비를 수행하고 반환값은 버립니다.
5.4.6. 선언 소비
참고: 이 알고리즘은 next input token이 이미 <ident-token>임을 확인한 상태임을 가정합니다.
선언 소비를 수행하려면:
consume the next input token을 수행합니다. 새 선언을 생성하고 이름을 current input token의 값으로 설정, 값은 초기 빈 리스트로 설정합니다.
- next input token이 <whitespace-token>인 동안, consume the next input token을 수행합니다.
-
next input
token이 <colon-token>이 아니면,
파싱 오류입니다.
아무것도 반환하지 않습니다.
그 밖의 경우, consume the next input token을 수행합니다.
- next input token이 <whitespace-token>인 동안, consume the next input token을 수행합니다.
- next input token이 <EOF-token>이 아닌 동안, 컴포넌트 값 소비를 수행하여 선언의 값에 추가합니다.
- 선언 값의 마지막 두 <whitespace-token>이 아닌 토큰이 값이 "!"인 <delim-token>과 값이 ASCII 대소문자 구분 없이 "important"인 <ident-token>이면, 이 둘을 선언 값에서 제거하고 선언의 important 플래그를 true로 설정합니다.
- 선언 값의 마지막 토큰이 <whitespace-token>인 동안, 해당 토큰 제거를 수행합니다.
- 선언을 반환합니다.
5.4.7. 컴포넌트 값 소비
컴포넌트 값 소비를 수행하려면:
다음 입력 토큰 소비를 수행하세요.
current input token이 <{-token>, <[-token>, 또는 <(-token>이면, 단순 블록 소비를 수행하고 반환하세요.
그 밖의 경우, current input token이 <function-token>이면, 함수 소비를 수행하고 반환하세요.
그 밖의 경우, current input token을 반환하세요.
5.4.8. 단순 블록 소비
참고: 이 알고리즘은 current input token이 <{-token>, <[-token>, 또는 <(-token>임을 이미 확인한 상태임을 가정합니다.
단순 블록 소비를 수행하려면:
ending token은 current input token의 짝이 되는 변형입니다. (예: <[-token>로 호출되었다면, ending token은 <]-token>입니다.)
단순 블록을 생성하고, 연관 토큰을 current input token으로 설정하며, 값은 초기 빈 리스트로 설정하세요.
next input token을 반복적으로 소비하고 다음과 같이 처리하세요:
- ending token
- 블록을 반환합니다.
- <EOF-token>
- 파싱 오류입니다. 블록을 반환합니다.
- anything else
- current input token 재소비. 컴포넌트 값 소비를 수행하고 블록의 값에 추가하세요.
참고: CSS에는 선언을 포함하는 블록과 한정 규칙을 포함하는 블록 사이에 불행한 구문적 모호성이 있습니다. 그래서 규칙을 처리하는 "consume" 알고리즘은 보다 구체적인 선언 목록 소비 또는 규칙 목록 소비 알고리즘 대신 처음에는 이 일반적인 알고리즘을 사용합니다. 보다 구체적인 알고리즘은 문법 적용 시, <declaration-list> 또는 <rule-list>/<stylesheet>를 포함하는지에 따라 호출됩니다.
5.4.9. 함수 소비
참고: 이 알고리즘은 current input token이 <function-token>임을 이미 확인한 상태임을 가정합니다.
함수 소비를 수행하려면:
current input token의 값을 이름으로 하는 함수를 생성하고, 값은 초기 빈 리스트로 설정하세요.
next input token을 반복적으로 소비하고 다음과 같이 처리하세요:
- <)-token>
- 함수를 반환합니다.
- <EOF-token>
- 파싱 오류입니다. 함수를 반환합니다.
- anything else
- current input token 재소비. 컴포넌트 값 소비를 수행하고 반환값을 함수의 값에 추가하세요.
6. An+B 마이크로 구문
CSS의 여러 기능, 예를 들어 :nth-child() 의사 클래스 등에서, 목록의 인덱스를 지정해야 할 때가 있습니다. An+B 마이크로 구문은 이런 경우에 유용하며, 저자가 목록에서 단일 요소나 일정 간격마다 모든 요소를 쉽게 지정할 수 있게 해줍니다.
An+B 표기법은 정수 단계(A)와 오프셋(B)을 정의하며, 목록의 An+B번째 요소를 나타냅니다. 여기서 n은 0 이상의 양의 정수일 때, 목록의 첫 번째 요소는 인덱스 1(0이 아님)을 갖습니다.
A와 B가 0보다 클 때, 목록을 A개씩 그룹으로 나누고 (마지막 그룹은 나머지), 각 그룹의 B번째 요소를 선택하게 됩니다.
An+B 표기법은 even과 odd 키워드도 허용하며, 각각 2n과 2n+1과 같은 의미입니다.
A와 B 값이 음수일 수도 있지만, n ≥ 0일 때 An+B의 양의 결과만 사용됩니다.
A와 B 모두 0이면, 해당 의사 클래스는 리스트 내 어떤 요소도 나타내지 않습니다.
6.1. 비공식 구문 설명
이 섹션은 비규범적입니다.
A가 0이면 An 부분은 생략 가능 (B 부분이 이미 생략된 경우 제외). An이 없고 B가 음수가 아니면, + 기호도 생략 가능. 이 경우 구문은 그냥 B로 간단해집니다.
A가 1 또는 -1이면,
규칙에서 1
을 생략할 수 있습니다.
B가 0이면, 매 A번째 요소를 선택합니다. 이런 경우 +B(또는 -B) 부분은 A 부분이 이미 생략된 경우를 제외하고 생략 가능합니다.
B가 음수일 때는 그 마이너스 기호가 + 기호를 대체합니다.
+ 또는 -로 An과 B를 구분할 때 양쪽에 공백이 허용됩니다(둘 다 있을 때).
6.2. <an+b>
타입
An+B 표기법은 원래 CSS의 다른 부분과는 약간 다른 토크나이저로 정의되어, CSS 토큰 관점에서 표현할 때 다소 특이하게 정의됩니다. 이 섹션은 CSS 토큰 관점에서 An+B 표기법을 인식하는 방법 (즉, CSS 문법 목적으로 <an+b> 타입을 정의)과, CSS 토큰을 해석하여 A와 B의 값을 얻는 방법을 설명합니다.
<an+b> 타입은 (Values & Units 명세의 값 정의 구문 사용) 다음과 같이 정의됩니다:
<an+b> = odd | even | <integer> | <n-dimension> | '+'?† n | -n | <ndashdigit-dimension> | '+'?† <ndashdigit-ident> | <dashndashdigit-ident> | <n-dimension> <signed-integer> | '+'?† n <signed-integer> | -n <signed-integer> | <ndash-dimension> <signless-integer> | '+'?† n- <signless-integer> | -n- <signless-integer> | <n-dimension> ['+' | '-'] <signless-integer> '+'?† n ['+' | '-'] <signless-integer> | -n ['+' | '-'] <signless-integer>
다음은 각 타입의 설명입니다:
<n-dimension>
: <dimension-token> 타입 플래그가 "integer"이고, 단위가 "n"(대소문자 불문)<ndash-dimension>
: <dimension-token> 타입 플래그가 "integer"이고, 단위가 "n-"(대소문자 불문)<ndashdigit-dimension>
: <dimension-token> 타입 플래그가 "integer"이고, 단위가 "n-*"("*"는 1개 이상의 digit, 대소문자 불문)<ndashdigit-ident>
: <ident-token> 값이 "n-*"("*"는 1개 이상의 digit, 대소문자 불문)<dashndashdigit-ident>
: <ident-token> 값이 "-n-*"("*"는 1개 이상의 digit, 대소문자 불문)<integer>
: <number-token> 타입 플래그가 "integer"<signed-integer>
: <number-token> 타입 플래그가 "integer"이고 representation이 "+" 또는 "-"로 시작<signless-integer>
: <number-token> 타입 플래그가 "integer"이고 representation이 digit으로 시작
†: "+" 기호 뒤에 "n"으로 시작하는 ident가 올 때는 두 토큰 사이에 공백이 없어야 하며, 그렇지 않으면 위 문법과 일치하지 않습니다. 그 밖의 토큰 사이에는 공백이 허용(무시)됩니다.
생성식의 각 절은 아래와 같이 해석합니다:
- odd
- A는 2, B는 1.
- even
- A는 2, B는 0.
<integer>
- A는 0, B는 정수 값.
<n-dimension>
'+'? n
-n
- A는 차원의 값, 1 또는 -1. B는 0.
<ndashdigit-dimension>
'+'? <ndashdigit-ident>
- A는 차원의 값 또는 1. B는 차원의 단위 또는 ident의 값에서 첫 code point를 제거하고 나머지를 10진수로 해석. B는 음수.
<dashndashdigit-ident>
- A는 -1. B는 ident의 값에서 처음 두 code point를 제거하고 나머지를 10진수로 해석. B는 음수.
<n-dimension> <signed-integer>
'+'? n <signed-integer>
-n <signed-integer>
- A는 차원의 값, 1 또는 -1. B는 정수 값.
<ndash-dimension> <signless-integer>
'+'? n- <signless-integer>
-n- <signless-integer>
- A는 차원의 값, 1 또는 -1. B는 정수의 음수값.
<n-dimension> ['+' | '-'] <signless-integer>
'+'? n ['+' | '-'] <signless-integer>
-n ['+' | '-'] <signless-integer>
- A는 차원의 값, 1 또는 -1. B는 정수값.
만약 사이에
'-'
가 있으면, B는 정수의 음수값이 됩니다.
7. 유니코드-Range 마이크로 구문
일부 구문(unicode-range 디스크립터와 @font-face 규칙 등)은 하나 이상의 유니코드 코드 포인트를 기술할 방법이 필요합니다. <urange> 생성식은 하나 이상의 유니코드 코드 포인트의 범위를 나타냅니다.
비공식적으로, <urange> 생성식에는 세 가지 형태가 있습니다:
- U+0001
- 이 경우 "1" 코드 포인트만 포함하는 단일 코드 포인트의 범위를 정의합니다.
- U+0001-00ff
- 첫 번째 값과 두 번째 값(이 경우 "1"에서 "ff"(10진수 255)까지 포함)의 범위를 정의합니다.
- U+00??
- "?" 문자가 모든 16진수 숫자로 대체되는 코드 포인트 범위를 정의합니다. 이 경우 U+0000-00ff과 동일한 범위를 정의합니다.
각 형태에서 16진수 숫자는 최대 6자리까지 허용됩니다("?"도 16진수로 간주).
7.1. <urange> 타입
<urange> 표기법은 원래 CSS에서 원시 토큰으로 정의되었지만, 실제로는 거의 사용되지 않고, 혼동을 주는 방식으로 <ident-token>과 충돌이 있습니다. 이 섹션에서는 기존 CSS 토큰 관점에서 <urange> 표기법을 인식하고, 그것을 유니코드 코드 포인트 범위로 해석하는 방법을 설명합니다.
어떤 혼동이 발생하나요?
예를 들어 CSS u + a { color: green;
}에서,
의도는 u
요소 뒤에 오는 a
요소에 녹색을 적용하는 것입니다.
일반적으로 콤비네이터와 선택자 사이에는 공백이 필요하지 않으므로,
minify하면 다음과 같이 됩니다:
다른 콤비네이터에서는 두 CSS가 동등하지만, 과거 unicode-range 토큰이 존재했기 때문에, minified 코드의 선택자 부분이 유니코드 범위로 해석되어, 두 idents와 콤비네이터가 아닌 unicode-range가 되어버립니다. 결과적으로 Selectors 문법과 일치하지 않아 규칙이 무효 처리됩니다.
(이 예시는 실제 Firefox에 보고된 버그에서 가져온 것입니다.)
참고: 여기서 설명하는 구문은 의도적으로 매우 저수준이며, 구현자를 위한 것입니다. 저자는 이전 섹션의 비공식 구문 설명을 참고해야 하며, <urange> 사용에 필요한 모든 정보를 제공합니다.
<urange> 타입은 (Values & Units 명세의 값 정의 구문 사용) 다음과 같이 정의됩니다:
<urange> = u '+' <ident-token> '?'* | u <dimension-token> '?'* | u <number-token> '?'* | u <number-token> <dimension-token> | u <number-token> <number-token> | u '+' '?'+
이 생성식에서는 어떤 토큰 사이에도 공백이 올 수 없습니다.
<urange> 생성식은 하나 이상의 연속된 유니코드 코드 포인트 범위를 start value와 end value라는 0 이상의 정수로 나타냅니다. 위 생성식을 범위로 해석하려면 다음 순서를 따릅니다:
-
첫 번째 u 토큰을 건너뛰고, 생성식 내 모든 토큰의 representation을 연결하여 text로 만듭니다.
-
text의 첫 글자가 U+002B PLUS SIGN이면 소비합니다. 그렇지 않으면, 이는 잘못된 <urange>이며, 알고리즘을 종료해야 합니다.
-
text에서 가능한 많은 16진수 숫자를 소비한 뒤, 가능한 많은 U+003F QUESTION MARK (?) 코드 포인트를 소비합니다. 만약 한 개도 코드 포인트를 소비하지 않았거나, 6개를 초과해서 소비했다면, 이는 잘못된 <urange>이며, 알고리즘을 종료해야 합니다.
만약 하나 이상의 U+003F QUESTION MARK (?) 코드 포인트를 소비했다면:
-
소비한 코드 포인트를 16진수 숫자로 해석하되, U+003F QUESTION MARK (?) 코드 포인트는 U+0030 DIGIT ZERO (0) 코드 포인트로 대체합니다. 이것이 start value입니다.
-
다시 소비한 코드 포인트를 16진수 숫자로 해석하되, 이번엔 U+003F QUESTION MARK (?) 코드 포인트를 U+0046 LATIN CAPITAL LETTER F (F) 코드 포인트로 대체합니다. 이것이 end value입니다.
-
알고리즘 종료.
그렇지 않으면, 소비한 코드 포인트를 16진수 숫자로 해석합니다. 이것이 start value입니다.
-
text에 코드 포인트가 남아있지 않으면, end value는 start value와 같으며, 알고리즘을 종료합니다.
-
text의 다음 코드 포인트가 U+002D HYPHEN-MINUS (-)이면 소비합니다. 그렇지 않으면, 이는 잘못된 <urange>이며, 알고리즘을 종료해야 합니다.
-
text에서 가능한 많은 16진수 숫자를 소비합니다.
한 개도 16진수를 소비하지 않았거나, 6개를 초과해서 소비했다면, 이는 잘못된 <urange>이며, 알고리즘을 종료해야 합니다. text에 코드 포인트가 남아있으면, 이는 잘못된 <urange>이며, 알고리즘을 종료해야 합니다.
-
소비한 코드 포인트를 16진수 숫자로 해석합니다. 이것이 end value입니다.
해당 <urange>가 어떤 코드 포인트 범위를 나타내는지 알아내려면:
-
end value가 최대 허용 코드 포인트보다 크면, <urange>는 무효이며 구문 오류입니다.
-
start value가 end value보다 크면, <urange>는 무효이며 구문 오류입니다.
-
그 밖의 경우 <urange>는 start value부터 end value까지(포함) 연속된 코드 포인트 범위를 나타냅니다.
참고: <urange>의 구문은 의도적으로 꽤 넓게 정의되어 있습니다; 비공식 구문에서 생성될 수 있는 모든 토큰 시퀀스를 포괄합니다. 그러나 구성 토큰 사이에 공백이 허용되지 않으므로 실제 사용 시에는 안전합니다. <urange> 뒤에 <number> 또는 <dimension>이 올 수 있는 문법에서도(저자가 <urange>를 ''u <number>'' 절로 지정하는 경우), 실제로는 매우 안전합니다. 저자가 <urange>와 <number>/<dimension> 사이를 공백이 아닌 주석으로 구분해야만 애매해질 수 있기 때문입니다. 따라서 혼동되는 방식으로 작성하는 것도 실제로는 드물고 작성하기도 어렵습니다.
8. 규칙 및 기타 값의 문법 정의
Values 명세는 속성의 문법을 정의하는 방법을 기술합니다. 이 섹션은 규칙의 문법 정의에 대해 다룹니다.
속성 문법과 마찬가지로,
<foo>
라는 표기는 해당 "foo" 문법 항을 참조하며,
정의가 다른 곳에 있다고 가정합니다.
<foo>
를 그 정의로 치환하면 의미적으로 동일한 문법이 됩니다.
여러 토큰 타입은 따옴표 없이 그대로 작성됩니다:
- <ident-token> (예:
auto
,disc
등)은 값 그대로 작성합니다. - <at-keyword-token>은 @ 문자와 토큰 값을 붙여
@media
처럼 작성합니다. - <function-token>은 함수 이름 뒤에 (를 붙여
translate(
처럼 작성합니다. - <colon-token>(
:
), <comma-token>(,
), <semicolon-token>(;
), <(-token>, <)-token>, <{-token>, <}-token> 등
토큰은 값이 문법에서 정의한 값과 일치하면 매칭됩니다. 별도 명시가 없다면 모든 매칭은 ASCII 대소문자 구분 없이 일치합니다.
참고: 이스케이프를 사용하면
<ident-token> 값이 (
로 끝나거나 @
로 시작하는 것을
만들 수 있지만,
그런 토큰은 <function-token>이나 <at-keyword-token>이 아니며, 해당 문법
정의와 매칭되지 않습니다.
<delim-token>은 값에 작은따옴표를 붙여 작성합니다.
예를 들어 "+" code point를 가진 <delim-token>은 '+'
로 작성합니다.
마찬가지로 <[-token>과 <]-token>도 작은따옴표로 작성해야 하며,
문법 자체에서 절을 그룹화할 때 사용됩니다.
<whitespace-token>은 문법에서 명시되지 않으며,
<whitespace-token>은 어떤 두 토큰 사이든, 앞뒤든
허용(명시적 정의가 없는 한).
(예: 규칙 프렐류드가 선택자인 경우, 공백은 의미가 있음.)
함수나 블록을 정의할 때, 끝 토큰도 문법에서 지정해야 하지만, 실제 토큰 스트림에 없더라도 매칭됩니다.
translateX( <translation-value> )
하지만 스타일시트가 함수가 닫히지 않은 상태로 끝날 수도 있습니다:
.foo { transform: translate(50px
CSS 파서는 이것을 함수 "translate"이라는 이름을 가진 선언 값으로 파싱합니다. 이런 경우 위 문법과 매칭됩니다. 끝 토큰이 토큰 스트림에 나타나지 않아도, 파서가 끝날 때 이미 끝 토큰의 존재 여부를 결정할 수 없으므로 블록과 함수가 있다는 사실만 남게 됩니다.
8.1. 블록 내용 정의: <declaration-list>, <rule-list>, <stylesheet> 생성식
CSS 파서는 블록의 내용(일부 at-규칙 끝에 오는 블록 등)에 대해 중립적입니다. 토큰 관점에서 블록의 일반 문법을 정의하는 것은 쉽지 않지만, 블록 파싱을 위한 명확하고 전용된 알고리즘이 정의되어 있습니다.
<style-block> 생성식은 스타일 규칙 블록의 내용을 나타냅니다. 문법에서는 블록 내 유일한 값으로만 사용할 수 있으며, 해당 블록 내용은 스타일 블록 내용 소비 알고리즘으로 파싱해야 함을 의미합니다.
<declaration-list> 생성식은 선언 리스트를 나타냅니다. 문법에서는 블록 내 유일한 값으로만 사용할 수 있으며, 해당 블록 내용은 선언 목록 소비 알고리즘으로 파싱해야 함을 의미합니다.
마찬가지로 <rule-list> 생성식은 규칙 리스트를 나타내며, 역시 블록 내 유일한 값으로만 사용할 수 있습니다. 해당 블록 내용은 규칙 목록 소비 알고리즘으로 파싱해야 함을 의미합니다.
마지막으로 <stylesheet> 생성식은 규칙 리스트를 나타내며, <rule-list>와 동일하지만, 이것을 사용하는 블록은 별도의 제한이 없는 모든 규칙을 기본적으로 허용합니다.
선언 허용 | 중첩 스타일 규칙 허용 | 임의 한정 규칙 허용 | at-규칙 허용 | 예시 | |
---|---|---|---|---|---|
<style-block> | ✓ | ✓ | ✗ | ✓ | 스타일 규칙, @nest, 중첩 조건 그룹 규칙 |
<declaration-list> | ✓ | ✗ | ✗ | ✓ | @font, @counter-style, @page, @keyframes 자식 규칙 등 |
<rule-list> | ✗ | ✗ | ✓ | ✓ | @keyframes, @font-feature-values |
<stylesheet> | ✗ | ✗ | ✓ | ✓ | 스타일시트, 비중첩 조건 그룹 규칙 |
특정 컨텍스트에서 at-규칙만 허용한다면, 예를 들어 @font-features-values처럼, 어떤 생성식을 사용해도 상관없지만, <rule-list>가 명칭상 더 명확하므로 선호됩니다.
@font-face { <declaration-list> }
이것만으로 규칙 문법 정의는 충분합니다.
또 다른 예로, @keyframes 규칙은 더 복잡하며, 프렐류드는 이름으로 해석되고, 블록에 keyframes 규칙이 들어갑니다. 문법은 다음과 같습니다:
@keyframes <keyframes-name> { <rule-list> }
<style-block>이나 <declaration-list>를 사용하는 규칙에서는, 해당 규칙 명세에서 규칙 안에서 유효한 속성, 디스크립터, at-규칙을 반드시 정의해야 합니다. 이는 "이 @foo 규칙은 이 명세/섹션에 정의된 속성/디스크립터를 허용한다."처럼 간단히 기술할 수 있고, 확장 명세에서는 "이 @foo 규칙은 다음 속성/디스크립터도 추가로 허용한다."처럼 기술할 수 있습니다. 블록 안에 유효하지 않은 선언이나 at-규칙이 있으면 반드시 규칙 값에서 제거해야 합니다.
<style-block> 또는 <declaration-list> 내에서는
!important
가 디스크립터에 자동으로 무효입니다.
규칙이 속성을 허용한다면,
해당 규칙 명세에서 속성이 cascade와 상호작용하는지,
구체성은 어떻게 되는지 정의해야 합니다.
cascade와 상호작용하지 않는다면 !important
가 포함된 속성은 자동으로 무효;
그렇지 않으면 !important
사용이 유효하며,
선언이 important로 간주되어 cascade에 반영됩니다.
[CSS-CASCADE-3] 참고.
<rule-list>를 사용하는 규칙에서는, 해당 규칙 명세에서 <declaration-list>와 마찬가지로 내부에서 어떤 규칙이 유효한지 반드시 정의해야 하며, 인식되지 않는 규칙은 규칙 값에서 제거해야 합니다.
<keyframe-rule> = <keyframe-selector> { <declaration-list> }
Keyframe 규칙에서는 선언으로 모든 애니메이션 가능한 CSS 속성과 animation-timing-function 속성만 허용하며, cascade와는 상호작용하지 않습니다.
<stylesheet>를 사용하는 규칙에서는, 기본적으로 모든 규칙을 허용하지만, 해당 규칙 명세에서 어떤 규칙이 무효인지 추가로 정의할 수 있습니다.
@media <media-query-list> { <stylesheet> }
또한 <stylesheet> 블록 내에서는 @media 규칙이 포함될 수 없음을 추가로 정의하며, 만약 나타나면 외부 규칙 값에서 삭제됩니다.
8.2. 임의 내용 정의: <declaration-value> 및 <any-value> 생성식
일부 문법에서는, 문법 내에서 어떤 적당한 입력도 허용하고, 내용에 대해 더 구체적인 오류 처리를 수동으로 하는 것이 유용할 수 있습니다 (문법 불일치가 전체를 무효로 만드는 것 대신).
예를 들어 커스텀 속성은 어떤 적당한 값도 허용하며, 다른 CSS 속성의 임의 부분을 포함하거나, CSS에 존재하지 않는 다양한 용도로 사용할 수 있습니다. 또 다른 예로 Media Queries의 <general-enclosed> 생성식은 MQ에서 앞으로 허용될 구문의 경계를 정의하며, "알 수 없는" 값에 대해 특별한 로직을 사용합니다.
이러한 목적을 위해 두 가지 추가 생성식이 정의됩니다:
<declaration-value> 생성식은 하나 이상의 토큰 시퀀스와 매칭되지만, 시퀀스에 <bad-string-token>, <bad-url-token>, 매칭되지 않는 <)-token>, <]-token>, <}-token>, 또는 최상위 <semicolon-token> 토큰, <delim-token> 값이 "!"인 토큰이 포함되어서는 안 됩니다. 이는 유효한 선언 값에 올 수 있는 모든 것을 나타냅니다.
<any-value> 생성식은 <declaration-value>와 동일하지만, 최상위 <semicolon-token> 토큰과 값이 "!"인 <delim-token> 토큰도 허용합니다. 이는 어떤 문맥에서든 올 수 있는 유효한 CSS 전체를 나타냅니다.
9. CSS 스타일시트
CSS 스타일시트 파싱을 하려면, 먼저 스타일시트 파싱을 수행합니다. 그 결과로 나온 모든 최상위 한정 규칙을 스타일 규칙으로 해석하며, 아래에서 정의합니다.
어떤 스타일 규칙이 무효이거나, 어떤 at-규칙이 인식되지 않거나 문법 또는 문맥상 무효라면, 파싱 오류로 간주하고, 해당 규칙을 버립니다.
9.1. 스타일 규칙
스타일 규칙은 한정 규칙 중 선택자 리스트와 속성 선언 리스트, 그리고 (선택적으로) 중첩 규칙 리스트를 연결하는 규칙입니다. rule set이라고도 하며, [CSS2]에서 사용됩니다. CSS Cascading and Inheritance [CSS-CASCADE-3]는 스타일 규칙 내부 선언이 cascade에 어떻게 참여하는지 정의합니다.
한정 규칙의 프렐류드는 CSS 문법에 따라 파싱하여 <selector-list>로 해석합니다. 만약 실패하면, 전체 스타일 규칙은 무효가 됩니다.
한정 규칙 블록의 내용은 스타일 블록 내용 파싱으로 해석합니다. 별도 명세나 이후 레벨에서 다르게 정의하지 않는 한, 해당 리스트 내 at-규칙은 무효이며 무시해야 합니다.
참고: [CSS-NESTING-1]에서는 @nest 및 조건 그룹 규칙이 스타일 규칙 안에 허용된다고 정의합니다.
알 수 없는 CSS 속성 선언이거나, 속성 값이 해당 속성의 구문과 일치하지 않으면 무효이며 무시됩니다. 스타일 규칙 내용의 유효성은 스타일 규칙 자체의 유효성에 영향을 주지 않습니다. 별도 명시가 없는 한, 속성 이름은 ASCII 대소문자 구분 없이 처리됩니다.
참고: 커스텀 속성의 이름([CSS-VARIABLES])은 대소문자를 구분합니다.
한정 규칙은 CSS 스타일시트 최상위에서는 스타일 규칙이 됩니다. 다른 문맥에서는 한정 규칙이 스타일 규칙일 수도 아닐 수도 있으며, 문맥에 따라 정의됩니다.
예를 들어, @media 규칙 내 한정 규칙([CSS3-CONDITIONAL])은 스타일 규칙이지만, @keyframes 규칙 내 한정 규칙([CSS3-ANIMATIONS])은 스타일 규칙이 아닙니다.
9.2. at-규칙
at-규칙은 at-keyword로 시작하는 규칙으로, 같은 문맥에서 스타일 규칙과 구분할 수 있습니다.
at-규칙의 용도:
-
스타일 규칙 및 기타 at-규칙을 그룹화/구조화(예: 조건 그룹 규칙)
-
특정 요소에 속하지 않는 스타일 정보 선언(예: 카운터 스타일 정의)
-
스타일 규칙이 처리하지 않는 기타 목적
at-규칙은 특정 규칙과 목적에 따라 다양한 형태를 가지지만, 크게 두 가지 종류가 있습니다: 문장 at-규칙(간단한 구문, 세미콜론으로 끝남), 블록 at-규칙({}-블록으로 끝나며, 중첩 한정 규칙, at-규칙, 선언을 가질 수 있음).
블록 at-규칙은 일반적으로 (일반 또는 at-규칙별) at-규칙, 한정 규칙, 디스크립터 선언을 포함하며, 이는 at-규칙마다 제한될 수 있습니다. 디스크립터는 속성과 유사하지만 (구문은 동일), 요소/박스가 아닌 특정 at-규칙 유형에 연결됩니다.
9.3. @charset 규칙
스타일시트의 대체 인코딩 결정 알고리즘은 파일 맨 앞에서 특정 바이트 시퀀스를 찾으며, 이는 "@charset"이라는 at-규칙 구문을 갖습니다.
하지만 실제로 at-규칙 "@charset"은 존재하지 않습니다. 스타일시트를 실제로 파싱할 때, @charset 규칙이 나타나면 인식되지 않은 규칙으로 간주되어 스타일시트 문법 검사에서 무효로 버려야 합니다.
참고: CSS 2.1에서는 @charset이 유효한 규칙이었습니다. 일부 레거시 명세에서는 @charset 규칙을 참조하고, 스타일시트 내 존재를 명시적으로 기술할 수도 있습니다.
10. 직렬화
이 명세에서 설명하는 토크나이저는 주석에 대해 토큰을 생성하지 않으며, 위치나 내용을 어떤 방식으로든 보존하지 않습니다. 구현체는 주석 내용과 위치를 토큰 스트림에 보존할 수 있습니다. 만약 보존한다면, 이 정보는 파싱 단계에 아무런 영향을 미치지 않아야 합니다.
이 명세에서는 CSS 직렬화 방법을 일반적으로 정의하지 않으며, 해당 작업은 [CSSOM] 및 각 기능 명세에 맡깁니다. 특히 주석과 공백의 직렬화는 정의되지 않습니다.
직렬화의 유일한 요구사항은 파싱과 "왕복(round-trip)"이 되어야 한다는 점입니다. 즉, 스타일시트 파싱 결과 데이터 구조가 파싱→직렬화→다시 파싱을 해도 동일해야 하며, 단, 연속된 <whitespace-token>은 하나로 합쳐질 수 있습니다.
참고: 이 예외는 CSS 문법이 아무 양의 공백도 하나의 공백과 동일하게 해석하기 때문에 가능합니다.
- U+005C REVERSE SOLIDUS (\)가 들어있는 <delim-token>은 U+005C REVERSE SOLIDUS와 줄바꿈(newline)을 이어서 직렬화해야 합니다. (토크나이저는 항상 해당 토큰 뒤에 줄바꿈으로 시작하는 <whitespace-token>만 생성합니다.)
- "unrestricted" 타입 플래그를 가진 <hash-token>은 "id" 타입 플래그를 가진 같은 토큰보다 이스케이프가 덜 필요할 수 있습니다.
- <dimension-token>의 단위는 과학적 표기와 구분하기 위해 이스케이프가 필요할 수 있습니다.
-
연속된 두 토큰 중,
첫 번째 토큰이 아래 표의 행 제목에 나타나고,
두 번째 토큰이 열 제목에 나타나며,
교차한 셀에 ✗가 있으면,
두 토큰 사이에 주석을 추가하여 직렬화해야 합니다.
토크나이저가 주석을 보존한다면, 보존된 주석을 사용해야 하며; 그렇지 않으면 빈 주석(
/**/
)을 추가해야 합니다. (보존된 주석은 아래 표에 관계없이 두 토큰 사이에 삽입될 수 있습니다.)행/열 제목의 단일 문자는 해당 값의 <delim-token>을 의미합니다. 단 "
(
"는 (-token을 의미합니다.
ident | function | url | bad url | - | number | percentage | dimension | CDC | ( | * | % | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
ident | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ||
at-keyword | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | |||
hash | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | |||
dimension | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | |||
# | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | |||
- | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | |||
number | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | |||
@ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ||||||
. | ✗ | ✗ | ✗ | |||||||||
+ | ✗ | ✗ | ✗ | |||||||||
/ | ✗ |
10.1. <an+b> 직렬화
-
A가 0이면, B를 직렬화한 결과를 반환하세요.
-
그 밖의 경우, result를 빈 문자열로 초기화하세요.
-
- A가
1
인 경우 -
result에 "n"을 추가하세요.
- A가
-1
인 경우 -
result에 "-n"을 추가하세요.
- A가 0이 아닌 경우
-
A를 직렬화하여 result에 추가하고, "n"을 result에 추가하세요.
- A가
-
- B가 0보다 큰 경우
-
result에 "+"를 추가하고, B를 직렬화한 결과를 result에 추가하세요.
- B가 0보다 작은 경우
-
B를 직렬화한 결과를 result에 추가하세요.
-
result를 반환하세요.
11. 프라이버시 및 보안 고려사항
이 명세는 새로운 프라이버시 문제를 도입하지 않습니다.
이 명세는 CSS 파싱이 모든 입력에 대해 명확하게 정의되어 있으므로 보안을 개선합니다.
기존 파서(화이트리스트/필터 등)가 이 명세와 다르게 파싱한다면, 다소 보안에 취약할 수 있지만, 이전 파싱 명세는 브라우저마다 다르게 해석되는 모호한 부분이 많았으므로, 그런 필터들은 이미 잠재적으로 안전하지 않았으며, 이 명세가 상황을 악화시키는 것은 아닙니다.
12. 변경 사항
이 섹션은 비규범적입니다.
12.1. 2019년 8월 16일 CR 버전 이후 변경 사항
다음과 같은 실질적 변경이 있었습니다:
-
새로운 § 5.3.2 CSS 문법에 따라 쉼표로 구분된 목록 파싱 알고리즘 추가.
-
새로운 § 5.3.7 스타일 블록 내용 파싱 알고리즘과 이에 대응하는 <style-block> 생성식 추가, 스타일 규칙이 이를 사용하도록 정의.
-
스타일시트 파싱을 Fetch 관련 사항과 정렬. (커밋 참고)
스타일시트 파싱을 input에서 선택적 url location을 받아 수행:
- ...
- 새 스타일시트 생성 , location을 location으로 설정(null일 수 있음).
- ...
다음과 같은 편집 변경이 있었습니다:
-
§ 9.2 at-규칙 추가: at-규칙, 문장 at-규칙, 블록 at-규칙, 디스크립터 정의 추가. (5633)
-
ident 시퀀스 용어 사용을 일관적으로 변경(이전에는 "name" 용어 혼용).
-
토큰화 이전 처리의 여러 단계에 명칭 부여 및 파싱 진입점에서 명시적으로 언급.
-
주석 삽입 표에 더 많은 항목 추가, ident가
--
로 시작할 수 있게 된 점 반영. (6874)
12.2. 2014년 2월 20일 CR 버전 이후 변경 사항
다음과 같은 실질적 변경이 있었습니다:
-
<unicode-range-token> 삭제, 대신 <urange> 생성식 도입.
-
문자열이 포함된 url() 함수는 이제 일반 <function-token>으로 파싱. "raw" URL을 포함하는 url() 함수는 여전히 <url-token>으로 특별 처리.
-
"Consume a URL token" 알고리즘 버그 수정: 문자열 시작 따옴표를 소비하지 않고 문자열 소비를 시도했던 부분.
-
여러 파서 알고리즘에서 current/next input token 관련 버그 수정(소비 시점 문제).
-
토큰화/파싱 알고리즘의 여러 버그 수정.
-
An ident-like token의 정의를 "--"로 시작할 수 있도록 변경. 이와 함께 consume a token의 "-" 단계 문항 순서도 rearrange하여 <CDC-token>을 -- <ident-token> 대신 인식하도록 함.
-
<an+b>에서 A가 1 또는 -1일 때 digit을 직렬화하지 않도록 변경.
-
모든 토큰에 representation 정의.
-
check if two code points are a valid escape의 마이너 버그 수정—
\ 뒤에 EOF가 오면 유효한 escape가 아님으로 처리. 스타일시트 맨 끝의 \는 이제 <delim-token>으로만 출력. -
@charset은 더 이상 유효한 CSS 규칙이 아님(단지 @charset이라는 이름의 "encoding declaration"처럼 보일 뿐)
-
파싱 시 선언 값 앞뒤의 공백 제거.
-
Selectors 전용 토큰 삭제, WG resolution에 따름.
-
surrogate를 입력 스트림에서 필터링, WG resolution에 따름. 이제 전체 명세는 scalar value만 처리.
다음과 같은 편집 변경이 있었습니다:
-
"Consume a string token" 알고리즘을 명시적 종료 토큰 없이 호출 가능하게 변경, current input token을 사용하는 형태가 기본이 됨. 알고리즘의 세 곳 호출부가 이 형태로 변경됨.
-
알고리즘의 사소한 편집적 구조 변경.
-
parse와 parse a comma-separated list of component values API 진입점 추가.
-
<declaration-value>와 <any-value> 생성식 추가.
-
"code point"와 "surrogate code point"를 Infra Standard의 동일 정의로 대체.
-
각 range가 포함 범위임을 명시적으로 기술.
-
주석 삽입 표에 열 추가, number token이 "%" delim token 옆에 올 때 처리.
댓글 처리 결과(Disposition of Comments) 제공.
12.3. 2013년 11월 5일 WD 버전 이후 변경 사항
- 직렬화 섹션을 재작성하여 오직 "왕복(round-trip)" 요구만 규범적으로 하고, 이를 위한 세부 방법은 note로 이동. 세부 corner case 일부 수정.
- [ENCODING]을 규범적 참고문헌에 추가. 이미 규범 텍스트에서 참조하고 있었으나, 목록에는 없었음.
-
스타일시트의 대체 인코딩 결정 알고리즘에서 @charset 바이트 시퀀스를 1024 바이트로 제한.
이는 HTML의
<meta charset>
와 동일하게 크기 제한을 두는 것. 이로 인해 인코딩 라벨 앞뒤 공백이 많은 경우에만 차이 발생:@charset " (공백 많음) utf-8";
12.4. 2013년 9월 19일 WD 버전 이후 변경 사항
- 환경 인코딩 개념 추가. 동작은 변하지 않으며, 일부 정의는 관련 명세로 옮겨야 함.
12.5. CSS 2.1 및 Selectors Level 3 이후 변경 사항
참고: 이 명세의 목적은 실제와 일치하는 것입니다; CSS2.1과 다른 점은 거의 항상 브라우저 동작과 맞지 않거나 미정의된 부분이 있었기 때문입니다. 브라우저와 불일치하는 세부사항이 있다면 꼭 알려주세요. 거의 확실히 의도하지 않은 부분일 것입니다.
바이트 스트림 디코딩 관련 변경:
- @charset 규칙은 ASCII 호환 바이트 패턴에서만 감지.
- @charset 규칙이 ASCII 비호환 인코딩을 지정하면 무시. 그런 경우 규칙 자체가 올바르게 디코드되지 않음.
- 문자 인코딩 참조는 IANA 레지스트리 대신 [ENCODING] 참조.
토큰화 관련 변경:
- CSS 소스 내 U+0000 NULL code point는 U+FFFD REPLACEMENT CHARACTER로 대체.
- \0 같은 16진수 이스케이프가 0으로 평가되면 U+FFFD REPLACEMENT CHARACTER 생성.
- non-ASCII code point 정의가 모든 ASCII 정의와 일치하도록 변경. 이에 따라 U+0080~U+009F code points가 ident code points가 됨(<delim-token>이 아님).
- 이제 토큰화에서 COMMENT나 BAD_COMMENT 토큰을 생성하지 않음. BAD_COMMENT는 이제 그냥 일반 토큰(오류 아님)으로 처리. 직렬화가 주석 삽입 책임을 가짐(예: 연속 <ident-token> 사이).
-
<unicode-range-token> 삭제,
저가치 및 부작용 발생 가능성 때문.
(u+a { font-weight: bold; }이 유효하지 않은 선택자였음...)
대신 <urange> 생성식 도입(토큰 패턴 기반). 기술적으로 2.1보다 느슨하지만(임의 개수의 숫자/? 허용), 실제 사용에는 영향 없음.
- EOF 오류 처리 규칙을 토크나이저에 적용, EOF에서는 BAD_STRING/BAD_URI 대신 정상 <string-token>, <url-token>만 생성.
- BAD_URI 토큰(현재 <bad-url-token>)은 "self-contained". 즉, 토크나이저가 <bad-url-token>임을 인식하면, 닫는 )만 찾고 나머지는 무시. 이런 동작은 더 복잡한 <function-token>처럼 블록 관리를 하지 않아 간단. WebKit만 이런 동작을 보이지만, 호환성 버그는 없음.
- <comma-token> 추가.
- <number-token>, <percentage-token>, <dimension-token>은 이제 앞의 +/- 기호를 값에 포함(별도 <delim-token>이 필요 없음). 이로 인해 +/-와 숫자 사이에 주석 삽입 불가.
- SVG와 일치하도록 숫자/백분율/단위에 과학적 표기 지원, WG resolution.
- surrogate에 대한 16진 이스케이프는 이제 대체 문자 출력(UTF-16 내부 사용 안전).
파싱 관련 변경:
- 선언 리스트는 이제 at-규칙도 허용(예: @page), WG resolution. 아직 정의되지 않은 at-규칙도 오류 처리에 영향 있음: at-규칙은 {} 블록에서 끝나며 세미콜론 없이 다음 선언 시작.
-
몇몇 특수 토큰(예: 매칭되지 않은 <}-token>)이 문법 곳곳에
나타날 때
적어도 한 브라우저가 보이는 합리적 동작을 명세에 포함.
이전에는 그런 토큰이 들어가면 스타일시트 문법과 일치하지 않아 처리 불명확.
구체적으로:
- []/()/함수 블록 내부에 {} 블록, <at-keyword-token>, <semicolon-token> 허용
- 한정 규칙 프렐류드는 세미콜론 허용
- 한정/at-규칙 프렐류드는 <at-keyword-token> 허용
An+B는 Selectors Level 3 [SELECT] 이후 다음과 같이 변경됨:
-
An+B 마이크로구문이 이제 별도 토크나이저가 아니라 CSS 토큰 관점에서 정의됨.
이에 따라 사소한 차이 있음:
- 일부 경우에 마이너스/숫자도 이스케이프 가능 (<dimension-token> 또는 <ident-token>의 단위 일부로 나올 때).
감사의 글
피드백과 기여에 감사드립니다: Anne van Kesteren, David Baron, Elika J. Etemad (fantasai), Henri Sivonen, Johannes Koch, 呂康豪 (Kang-Hao Lu), Marc O’Morain, Raffaello Giulietti, Simon Pieter, Tyler Karaszewski, 그리고 Zack Weinberg.