lui-templates 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lui-templates",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "transform html templates into lui components",
5
5
  "repository": {
6
6
  "type": "git",
package/src/parser.js CHANGED
@@ -55,3 +55,136 @@ export const html_is_self_closing = tag => html_self_closing.includes(tag);
55
55
 
56
56
  const html_boolean_attrs = new Set('disabled,checked,selected,readonly,required,autofocus,autoplay,controls,loop,muted,open,hidden,multiple,defer,async,novalidate,formnovalidate'.split(','));
57
57
  export const html_is_boolean_attr = attr => html_boolean_attrs.has(attr.toLowerCase());
58
+
59
+ const html_entity_map = new Map([
60
+ // Common punctuation and symbols
61
+ ['lt', '<'],
62
+ ['gt', '>'],
63
+ ['amp', '&'],
64
+ ['quot', '"'],
65
+ ['apos', "'"],
66
+ // Common Latin characters with diacritics
67
+ ['auml', 'ä'],
68
+ ['Auml', 'Ä'],
69
+ ['ouml', 'ö'],
70
+ ['Ouml', 'Ö'],
71
+ ['uuml', 'ü'],
72
+ ['Uuml', 'Ü'],
73
+ ['szlig', 'ß'],
74
+ ['euml', 'ë'],
75
+ ['Euml', 'Ë'],
76
+ ['iuml', 'ï'],
77
+ ['Iuml', 'Ï'],
78
+ ['yuml', 'ÿ'],
79
+ ['Yuml', 'Ÿ'],
80
+ ['aacute', 'á'],
81
+ ['Aacute', 'Á'],
82
+ ['eacute', 'é'],
83
+ ['Eacute', 'É'],
84
+ ['iacute', 'í'],
85
+ ['Iacute', 'Í'],
86
+ ['oacute', 'ó'],
87
+ ['Oacute', 'Ó'],
88
+ ['uacute', 'ú'],
89
+ ['Uacute', 'Ú'],
90
+ ['yacute', 'ý'],
91
+ ['Yacute', 'Ý'],
92
+ ['agrave', 'à'],
93
+ ['Agrave', 'À'],
94
+ ['egrave', 'è'],
95
+ ['Egrave', 'È'],
96
+ ['igrave', 'ì'],
97
+ ['Igrave', 'Ì'],
98
+ ['ograve', 'ò'],
99
+ ['Ograve', 'Ò'],
100
+ ['ugrave', 'ù'],
101
+ ['Ugrave', 'Ù'],
102
+ ['acirc', 'â'],
103
+ ['Acirc', 'Â'],
104
+ ['ecirc', 'ê'],
105
+ ['Ecirc', 'Ê'],
106
+ ['icirc', 'î'],
107
+ ['Icirc', 'Î'],
108
+ ['ocirc', 'ô'],
109
+ ['Ocirc', 'Ô'],
110
+ ['ucirc', 'û'],
111
+ ['Ucirc', 'Û'],
112
+ ['atilde', 'ã'],
113
+ ['Atilde', 'Ã'],
114
+ ['ntilde', 'ñ'],
115
+ ['Ntilde', 'Ñ'],
116
+ ['otilde', 'õ'],
117
+ ['Otilde', 'Õ'],
118
+ ['aring', 'å'],
119
+ ['Aring', 'Å'],
120
+ ['ccedil', 'ç'],
121
+ ['Ccedil', 'Ç'],
122
+ ['aelig', 'æ'],
123
+ ['AElig', 'Æ'],
124
+ ['oslash', 'ø'],
125
+ ['Oslash', 'Ø'],
126
+ ['eth', 'ð'],
127
+ ['ETH', 'Ð'],
128
+ ['thorn', 'þ'],
129
+ ['THORN', 'Þ'],
130
+ // Common symbols and special characters
131
+ ['nbsp', '\u00A0'],
132
+ ['copy', '©'],
133
+ ['reg', '®'],
134
+ ['trade', '™'],
135
+ ['euro', '€'],
136
+ ['cent', '¢'],
137
+ ['pound', '£'],
138
+ ['yen', '¥'],
139
+ ['sect', '§'],
140
+ ['para', '¶'],
141
+ ['deg', '°'],
142
+ ['plusmn', '±'],
143
+ ['micro', 'µ'],
144
+ ['middot', '·'],
145
+ ['bull', '•'],
146
+ ['hellip', '…'],
147
+ ['prime', '′'],
148
+ ['Prime', '″'],
149
+ ['lsquo', '\u2018'],
150
+ ['rsquo', '\u2019'],
151
+ ['ldquo', '\u201C'],
152
+ ['rdquo', '\u201D'],
153
+ ['sbquo', '\u201A'],
154
+ ['bdquo', '\u201E'],
155
+ ['dagger', '†'],
156
+ ['Dagger', '‡'],
157
+ ['permil', '‰'],
158
+ ['lsaquo', '‹'],
159
+ ['rsaquo', '›'],
160
+ ['ndash', '\u2013'],
161
+ ['mdash', '\u2014'],
162
+ ['minus', '−'],
163
+ ['times', '×'],
164
+ ['divide', '÷'],
165
+ ['frac14', '¼'],
166
+ ['frac12', '½'],
167
+ ['frac34', '¾'],
168
+ ]);
169
+
170
+ function html_entity_translate(match, entity) {
171
+ if (entity[0] === '#') {
172
+ const codePoint = (
173
+ entity[1].toLowerCase() === 'x'
174
+ ? parseInt(entity.slice(2), 16)
175
+ : parseInt(entity.slice(1), 10)
176
+ );
177
+ if (
178
+ codePoint >= 0 && codePoint < 0x110000 &&
179
+ (codePoint < 0xD800 || codePoint >= 0xE000)
180
+ ) {
181
+ return String.fromCodePoint(codePoint);
182
+ }
183
+ }
184
+ return html_entity_map.get(entity) || match;
185
+ }
186
+
187
+ export const html_unescape = text => text.replace(
188
+ /&([a-zA-Z][a-zA-Z0-9]*|#[0-9]+|#[xX][0-9a-fA-F]+);/g,
189
+ html_entity_translate
190
+ );
@@ -3,14 +3,15 @@ import {
3
3
  VALUE_TYPE_STATIC,
4
4
  } from '../constants.js';
5
5
  import {
6
+ html_attr_to_dom,
6
7
  html_is_self_closing,
7
8
  html_is_whitespace,
8
- html_attr_to_dom,
9
+ html_unescape,
9
10
  html_whitespaces,
10
11
  } from '../parser.js';
11
12
 
12
- const TOKEN_HTML_START = 0;
13
- const TOKEN_HTML_END = 1;
13
+ const TOKEN_TAG_START = 0;
14
+ const TOKEN_TAG_END = 1;
14
15
  const TOKEN_TEXT = 2;
15
16
 
16
17
  export default async function parse_html(src, path) {
@@ -140,7 +141,7 @@ class Tokenizer {
140
141
  this.chars_consume('>');
141
142
 
142
143
  tokens.push({
143
- type: TOKEN_HTML_END,
144
+ type: TOKEN_TAG_END,
144
145
  ...position,
145
146
  tag_name,
146
147
  });
@@ -175,7 +176,7 @@ class Tokenizer {
175
176
  this.chars_consume('>');
176
177
 
177
178
  const start_token = {
178
- type: TOKEN_HTML_START,
179
+ type: TOKEN_TAG_START,
179
180
  ...position,
180
181
  tag_name,
181
182
  props,
@@ -188,7 +189,7 @@ class Tokenizer {
188
189
  return [
189
190
  start_token,
190
191
  {
191
- type: TOKEN_HTML_END,
192
+ type: TOKEN_TAG_END,
192
193
  ...position,
193
194
  tag_name,
194
195
  }
@@ -250,7 +251,7 @@ function build_nodes(tokens, index, index_end) {
250
251
  for (; index < index_end; index++) {
251
252
  const token = tokens[index];
252
253
  switch (token.type) {
253
- case TOKEN_HTML_START: {
254
+ case TOKEN_TAG_START: {
254
255
  const {tag_name, props} = token;
255
256
  const index_start = ++index;
256
257
 
@@ -259,10 +260,10 @@ function build_nodes(tokens, index, index_end) {
259
260
  loop: for (; index < index_end; index++) {
260
261
  const token = tokens[index];
261
262
  switch (token.type) {
262
- case TOKEN_HTML_START:
263
+ case TOKEN_TAG_START:
263
264
  if (token.tag_name === tag_name) depth++;
264
265
  break;
265
- case TOKEN_HTML_END:
266
+ case TOKEN_TAG_END:
266
267
  if (
267
268
  token.tag_name === tag_name &&
268
269
  --depth === 0
@@ -291,7 +292,7 @@ function build_nodes(tokens, index, index_end) {
291
292
  });
292
293
  break;
293
294
  }
294
- case TOKEN_HTML_END:
295
+ case TOKEN_TAG_END:
295
296
  error(`Unexpected closing tag </${token.tag_name}>`, token);
296
297
  case TOKEN_TEXT: {
297
298
  let {value} = token;
@@ -333,7 +334,7 @@ function build_nodes(tokens, index, index_end) {
333
334
  props: {
334
335
  innerText: {
335
336
  type: VALUE_TYPE_STATIC,
336
- data: value,
337
+ data: html_unescape(value),
337
338
  },
338
339
  },
339
340
  children: [],