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