• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const { DOCUMENT_MODE } = require('./html');
4
5//Const
6const VALID_DOCTYPE_NAME = 'html';
7const VALID_SYSTEM_ID = 'about:legacy-compat';
8const QUIRKS_MODE_SYSTEM_ID = 'http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd';
9
10const QUIRKS_MODE_PUBLIC_ID_PREFIXES = [
11    '+//silmaril//dtd html pro v0r11 19970101//',
12    '-//as//dtd html 3.0 aswedit + extensions//',
13    '-//advasoft ltd//dtd html 3.0 aswedit + extensions//',
14    '-//ietf//dtd html 2.0 level 1//',
15    '-//ietf//dtd html 2.0 level 2//',
16    '-//ietf//dtd html 2.0 strict level 1//',
17    '-//ietf//dtd html 2.0 strict level 2//',
18    '-//ietf//dtd html 2.0 strict//',
19    '-//ietf//dtd html 2.0//',
20    '-//ietf//dtd html 2.1e//',
21    '-//ietf//dtd html 3.0//',
22    '-//ietf//dtd html 3.2 final//',
23    '-//ietf//dtd html 3.2//',
24    '-//ietf//dtd html 3//',
25    '-//ietf//dtd html level 0//',
26    '-//ietf//dtd html level 1//',
27    '-//ietf//dtd html level 2//',
28    '-//ietf//dtd html level 3//',
29    '-//ietf//dtd html strict level 0//',
30    '-//ietf//dtd html strict level 1//',
31    '-//ietf//dtd html strict level 2//',
32    '-//ietf//dtd html strict level 3//',
33    '-//ietf//dtd html strict//',
34    '-//ietf//dtd html//',
35    '-//metrius//dtd metrius presentational//',
36    '-//microsoft//dtd internet explorer 2.0 html strict//',
37    '-//microsoft//dtd internet explorer 2.0 html//',
38    '-//microsoft//dtd internet explorer 2.0 tables//',
39    '-//microsoft//dtd internet explorer 3.0 html strict//',
40    '-//microsoft//dtd internet explorer 3.0 html//',
41    '-//microsoft//dtd internet explorer 3.0 tables//',
42    '-//netscape comm. corp.//dtd html//',
43    '-//netscape comm. corp.//dtd strict html//',
44    "-//o'reilly and associates//dtd html 2.0//",
45    "-//o'reilly and associates//dtd html extended 1.0//",
46    "-//o'reilly and associates//dtd html extended relaxed 1.0//",
47    '-//sq//dtd html 2.0 hotmetal + extensions//',
48    '-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//',
49    '-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//',
50    '-//spyglass//dtd html 2.0 extended//',
51    '-//sun microsystems corp.//dtd hotjava html//',
52    '-//sun microsystems corp.//dtd hotjava strict html//',
53    '-//w3c//dtd html 3 1995-03-24//',
54    '-//w3c//dtd html 3.2 draft//',
55    '-//w3c//dtd html 3.2 final//',
56    '-//w3c//dtd html 3.2//',
57    '-//w3c//dtd html 3.2s draft//',
58    '-//w3c//dtd html 4.0 frameset//',
59    '-//w3c//dtd html 4.0 transitional//',
60    '-//w3c//dtd html experimental 19960712//',
61    '-//w3c//dtd html experimental 970421//',
62    '-//w3c//dtd w3 html//',
63    '-//w3o//dtd w3 html 3.0//',
64    '-//webtechs//dtd mozilla html 2.0//',
65    '-//webtechs//dtd mozilla html//'
66];
67
68const QUIRKS_MODE_NO_SYSTEM_ID_PUBLIC_ID_PREFIXES = QUIRKS_MODE_PUBLIC_ID_PREFIXES.concat([
69    '-//w3c//dtd html 4.01 frameset//',
70    '-//w3c//dtd html 4.01 transitional//'
71]);
72
73const QUIRKS_MODE_PUBLIC_IDS = ['-//w3o//dtd w3 html strict 3.0//en//', '-/w3c/dtd html 4.0 transitional/en', 'html'];
74const LIMITED_QUIRKS_PUBLIC_ID_PREFIXES = ['-//w3c//dtd xhtml 1.0 frameset//', '-//w3c//dtd xhtml 1.0 transitional//'];
75
76const LIMITED_QUIRKS_WITH_SYSTEM_ID_PUBLIC_ID_PREFIXES = LIMITED_QUIRKS_PUBLIC_ID_PREFIXES.concat([
77    '-//w3c//dtd html 4.01 frameset//',
78    '-//w3c//dtd html 4.01 transitional//'
79]);
80
81//Utils
82function enquoteDoctypeId(id) {
83    const quote = id.indexOf('"') !== -1 ? "'" : '"';
84
85    return quote + id + quote;
86}
87
88function hasPrefix(publicId, prefixes) {
89    for (let i = 0; i < prefixes.length; i++) {
90        if (publicId.indexOf(prefixes[i]) === 0) {
91            return true;
92        }
93    }
94
95    return false;
96}
97
98//API
99exports.isConforming = function(token) {
100    return (
101        token.name === VALID_DOCTYPE_NAME &&
102        token.publicId === null &&
103        (token.systemId === null || token.systemId === VALID_SYSTEM_ID)
104    );
105};
106
107exports.getDocumentMode = function(token) {
108    if (token.name !== VALID_DOCTYPE_NAME) {
109        return DOCUMENT_MODE.QUIRKS;
110    }
111
112    const systemId = token.systemId;
113
114    if (systemId && systemId.toLowerCase() === QUIRKS_MODE_SYSTEM_ID) {
115        return DOCUMENT_MODE.QUIRKS;
116    }
117
118    let publicId = token.publicId;
119
120    if (publicId !== null) {
121        publicId = publicId.toLowerCase();
122
123        if (QUIRKS_MODE_PUBLIC_IDS.indexOf(publicId) > -1) {
124            return DOCUMENT_MODE.QUIRKS;
125        }
126
127        let prefixes = systemId === null ? QUIRKS_MODE_NO_SYSTEM_ID_PUBLIC_ID_PREFIXES : QUIRKS_MODE_PUBLIC_ID_PREFIXES;
128
129        if (hasPrefix(publicId, prefixes)) {
130            return DOCUMENT_MODE.QUIRKS;
131        }
132
133        prefixes =
134            systemId === null ? LIMITED_QUIRKS_PUBLIC_ID_PREFIXES : LIMITED_QUIRKS_WITH_SYSTEM_ID_PUBLIC_ID_PREFIXES;
135
136        if (hasPrefix(publicId, prefixes)) {
137            return DOCUMENT_MODE.LIMITED_QUIRKS;
138        }
139    }
140
141    return DOCUMENT_MODE.NO_QUIRKS;
142};
143
144exports.serializeContent = function(name, publicId, systemId) {
145    let str = '!DOCTYPE ';
146
147    if (name) {
148        str += name;
149    }
150
151    if (publicId) {
152        str += ' PUBLIC ' + enquoteDoctypeId(publicId);
153    } else if (systemId) {
154        str += ' SYSTEM';
155    }
156
157    if (systemId !== null) {
158        str += ' ' + enquoteDoctypeId(systemId);
159    }
160
161    return str;
162};
163