.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / dom-serializer / index.js
1 /*
2   Module dependencies
3 */
4 var ElementType = require('domelementtype');
5 var entities = require('entities');
6
7 /* mixed-case SVG and MathML tags & attributes
8    recognized by the HTML parser, see
9    https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inforeign
10 */
11 var foreignNames = require('./foreignNames.json');
12 foreignNames.elementNames.__proto__ = null; /* use as a simple dictionary */
13 foreignNames.attributeNames.__proto__ = null;
14
15 var unencodedElements = {
16   __proto__: null,
17   style: true,
18   script: true,
19   xmp: true,
20   iframe: true,
21   noembed: true,
22   noframes: true,
23   plaintext: true,
24   noscript: true
25 };
26
27 /*
28   Format attributes
29 */
30 function formatAttrs(attributes, opts) {
31   if (!attributes) return;
32
33   var output = '';
34   var value;
35
36   // Loop through the attributes
37   for (var key in attributes) {
38     value = attributes[key];
39     if (output) {
40       output += ' ';
41     }
42
43     if (opts.xmlMode === 'foreign') {
44       /* fix up mixed-case attribute names */
45       key = foreignNames.attributeNames[key] || key;
46     }
47     output += key;
48     if ((value !== null && value !== '') || opts.xmlMode) {
49       output +=
50         '="' +
51         (opts.decodeEntities
52           ? entities.encodeXML(value)
53           : value.replace(/\"/g, '"')) +
54         '"';
55     }
56   }
57
58   return output;
59 }
60
61 /*
62   Self-enclosing tags (stolen from node-htmlparser)
63 */
64 var singleTag = {
65   __proto__: null,
66   area: true,
67   base: true,
68   basefont: true,
69   br: true,
70   col: true,
71   command: true,
72   embed: true,
73   frame: true,
74   hr: true,
75   img: true,
76   input: true,
77   isindex: true,
78   keygen: true,
79   link: true,
80   meta: true,
81   param: true,
82   source: true,
83   track: true,
84   wbr: true
85 };
86
87 var render = (module.exports = function(dom, opts) {
88   if (!Array.isArray(dom) && !dom.cheerio) dom = [dom];
89   opts = opts || {};
90
91   var output = '';
92
93   for (var i = 0; i < dom.length; i++) {
94     var elem = dom[i];
95
96     if (elem.type === 'root') output += render(elem.children, opts);
97     else if (ElementType.isTag(elem)) output += renderTag(elem, opts);
98     else if (elem.type === ElementType.Directive)
99       output += renderDirective(elem);
100     else if (elem.type === ElementType.Comment) output += renderComment(elem);
101     else if (elem.type === ElementType.CDATA) output += renderCdata(elem);
102     else output += renderText(elem, opts);
103   }
104
105   return output;
106 });
107
108 var foreignModeIntegrationPoints = [
109   'mi',
110   'mo',
111   'mn',
112   'ms',
113   'mtext',
114   'annotation-xml',
115   'foreignObject',
116   'desc',
117   'title'
118 ];
119
120 function renderTag(elem, opts) {
121   // Handle SVG / MathML in HTML
122   if (opts.xmlMode === 'foreign') {
123     /* fix up mixed-case element names */
124     elem.name = foreignNames.elementNames[elem.name] || elem.name;
125     /* exit foreign mode at integration points */
126     if (
127       elem.parent &&
128       foreignModeIntegrationPoints.indexOf(elem.parent.name) >= 0
129     )
130       opts = Object.assign({}, opts, { xmlMode: false });
131   }
132   if (!opts.xmlMode && ['svg', 'math'].indexOf(elem.name) >= 0) {
133     opts = Object.assign({}, opts, { xmlMode: 'foreign' });
134   }
135
136   var tag = '<' + elem.name;
137   var attribs = formatAttrs(elem.attribs, opts);
138
139   if (attribs) {
140     tag += ' ' + attribs;
141   }
142
143   if (opts.xmlMode && (!elem.children || elem.children.length === 0)) {
144     tag += '/>';
145   } else {
146     tag += '>';
147     if (elem.children) {
148       tag += render(elem.children, opts);
149     }
150
151     if (!singleTag[elem.name] || opts.xmlMode) {
152       tag += '</' + elem.name + '>';
153     }
154   }
155
156   return tag;
157 }
158
159 function renderDirective(elem) {
160   return '<' + elem.data + '>';
161 }
162
163 function renderText(elem, opts) {
164   var data = elem.data || '';
165
166   // if entities weren't decoded, no need to encode them back
167   if (
168     opts.decodeEntities &&
169     !(elem.parent && elem.parent.name in unencodedElements)
170   ) {
171     data = entities.encodeXML(data);
172   }
173
174   return data;
175 }
176
177 function renderCdata(elem) {
178   return '<![CDATA[' + elem.children[0].data + ']]>';
179 }
180
181 function renderComment(elem) {
182   return '<!--' + elem.data + '-->';
183 }