@jdeighan/coffee-utils 14.0.31 → 14.0.33

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,7 +1,7 @@
1
1
  {
2
2
  "name": "@jdeighan/coffee-utils",
3
3
  "type": "module",
4
- "version": "14.0.31",
4
+ "version": "14.0.33",
5
5
  "description": "A set of utility functions for CoffeeScript",
6
6
  "main": "coffee_utils.js",
7
7
  "exports": {
@@ -45,14 +45,14 @@
45
45
  },
46
46
  "homepage": "https://github.com/johndeighan/coffee-utils#readme",
47
47
  "dependencies": {
48
- "@jdeighan/base-utils": "^4.0.15",
48
+ "@jdeighan/base-utils": "^4.0.19",
49
49
  "cross-env": "^7.0.3",
50
50
  "n-readlines": "^1.0.1",
51
51
  "readline-sync": "^1.4.10",
52
52
  "svelte": "^3.55.1"
53
53
  },
54
54
  "devDependencies": {
55
- "@jdeighan/unit-tester": "^3.0.39",
55
+ "@jdeighan/unit-tester": "^3.0.41",
56
56
  "ava": "^5.1.1"
57
57
  }
58
58
  }
package/src/html.coffee CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  import {assert, croak} from '@jdeighan/base-utils/exceptions'
4
4
  import {
5
- undef, pass, words, isEmpty, nonEmpty, toBlock,
5
+ undef, pass, words, isEmpty, nonEmpty, toBlock, OL, getOptions,
6
6
  } from '@jdeighan/base-utils'
7
+ import {dbgEnter, dbgReturn, dbg} from '@jdeighan/base-utils/debug'
7
8
  import {indented} from '@jdeighan/coffee-utils/indent'
8
9
 
9
10
  hNoEnd = {}
@@ -211,3 +212,58 @@ export elem = (tagName, hAttr=undef, text=undef, oneIndent="\t") =>
211
212
  indented(text, 1, oneIndent)
212
213
  tag2str(hToken, 'end')
213
214
  ])
215
+
216
+ # ---------------------------------------------------------------------------
217
+
218
+ export formatHTML = (html, hOptions={}) =>
219
+
220
+ dbgEnter 'formatHTML', html, hOptions
221
+ {oneIndent} = getOptions(hOptions, {
222
+ oneIndent: ' '
223
+ })
224
+
225
+ html = html.trim() # remove any leading/trailing whitespace
226
+ assert html.charAt(0) == '<', "Bad HTML, no < at start"
227
+ assert html.charAt(html.length-1) == '>', "Bad HTML, no > at end"
228
+
229
+ # --- Remove leading '<' and trailing '>'
230
+ html = html.substring(1, html.length-1)
231
+
232
+ hNoEndTag = {}
233
+ for tag in words("""
234
+ br hr img input link base
235
+ meta param area embed
236
+ col track source
237
+ """)
238
+ hNoEndTag[tag] = true
239
+
240
+ lParts = []
241
+ level = 0
242
+
243
+ for elem in html.split(/>\s*</)
244
+ dbg "ELEM: #{OL(elem)}"
245
+ [_, endMarker, tagName, rest] = elem.match(///^
246
+ (\/)? # possible end tag
247
+ ([A-Za-z][A-Za-z0-9-]*) # tag name
248
+ (.*) # everything else
249
+ $///)
250
+ if endMarker
251
+ dbg " TAG: #{OL(tagName)} - END MARKER"
252
+ else
253
+ dbg " TAG: #{OL(tagName)} - NO END MARKER"
254
+
255
+ if endMarker && (level > 0)
256
+ # --- If end tag, reduce level
257
+ dbg " reduce level #{level} to #{level-1}"
258
+ level -= 1
259
+
260
+ dbg " ADD #{OL(elem)} at level #{level}"
261
+ lParts.push oneIndent.repeat(level), "<#{elem}>\n"
262
+
263
+ if ! endMarker && ! hNoEndTag[tagName] && !rest.endsWith('/'+tagName)
264
+ dbg " inc level #{level} to #{level+1}"
265
+ level += 1
266
+
267
+ result = lParts.join('').trim()
268
+ dbgReturn 'formatHTML', result
269
+ return result
package/src/html.js CHANGED
@@ -13,9 +13,17 @@ import {
13
13
  words,
14
14
  isEmpty,
15
15
  nonEmpty,
16
- toBlock
16
+ toBlock,
17
+ OL,
18
+ getOptions
17
19
  } from '@jdeighan/base-utils';
18
20
 
21
+ import {
22
+ dbgEnter,
23
+ dbgReturn,
24
+ dbg
25
+ } from '@jdeighan/base-utils/debug';
26
+
19
27
  import {
20
28
  indented
21
29
  } from '@jdeighan/coffee-utils/indent';
@@ -214,3 +222,54 @@ export var elem = (tagName, hAttr = undef, text = undef, oneIndent = "\t") => {
214
222
  return toBlock([tag2str(hToken, 'begin'), indented(text, 1, oneIndent), tag2str(hToken, 'end')]);
215
223
  }
216
224
  };
225
+
226
+ // ---------------------------------------------------------------------------
227
+ export var formatHTML = (html, hOptions = {}) => {
228
+ var _, endMarker, hNoEndTag, j, k, lParts, len1, len2, level, oneIndent, ref1, ref2, rest, result, tag;
229
+ dbgEnter('formatHTML', html, hOptions);
230
+ ({oneIndent} = getOptions(hOptions, {
231
+ oneIndent: ' '
232
+ }));
233
+ html = html.trim(); // remove any leading/trailing whitespace
234
+ assert(html.charAt(0) === '<', "Bad HTML, no < at start");
235
+ assert(html.charAt(html.length - 1) === '>', "Bad HTML, no > at end");
236
+ // --- Remove leading '<' and trailing '>'
237
+ html = html.substring(1, html.length - 1);
238
+ hNoEndTag = {};
239
+ ref1 = words(`br hr img input link base
240
+ meta param area embed
241
+ col track source`);
242
+ for (j = 0, len1 = ref1.length; j < len1; j++) {
243
+ tag = ref1[j];
244
+ hNoEndTag[tag] = true;
245
+ }
246
+ lParts = [];
247
+ level = 0;
248
+ ref2 = html.split(/>\s*</);
249
+ for (k = 0, len2 = ref2.length; k < len2; k++) {
250
+ elem = ref2[k];
251
+ dbg(`ELEM: ${OL(elem)}`);
252
+ [_, endMarker, tagName, rest] = elem.match(/^(\/)?([A-Za-z][A-Za-z0-9-]*)(.*)$/); // possible end tag
253
+ // tag name
254
+ // everything else
255
+ if (endMarker) {
256
+ dbg(` TAG: ${OL(tagName)} - END MARKER`);
257
+ } else {
258
+ dbg(` TAG: ${OL(tagName)} - NO END MARKER`);
259
+ }
260
+ if (endMarker && (level > 0)) {
261
+ // --- If end tag, reduce level
262
+ dbg(` reduce level ${level} to ${level - 1}`);
263
+ level -= 1;
264
+ }
265
+ dbg(` ADD ${OL(elem)} at level ${level}`);
266
+ lParts.push(oneIndent.repeat(level), `<${elem}>\n`);
267
+ if (!endMarker && !hNoEndTag[tagName] && !rest.endsWith('/' + tagName)) {
268
+ dbg(` inc level ${level} to ${level + 1}`);
269
+ level += 1;
270
+ }
271
+ }
272
+ result = lParts.join('').trim();
273
+ dbgReturn('formatHTML', result);
274
+ return result;
275
+ };