@jdeighan/coffee-utils 10.0.1 → 10.0.4
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 +2 -1
- package/src/SectionMap.coffee +19 -11
- package/src/SectionMap.js +19 -12
- package/src/block_utils.coffee +1 -1
- package/src/block_utils.js +2 -1
- package/src/html_utils.coffee +217 -0
- package/src/html_utils.js +222 -0
- package/src/indent_utils.coffee +0 -11
- package/src/indent_utils.js +0 -6
- package/src/log_utils.coffee +6 -1
- package/src/log_utils.js +8 -2
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@jdeighan/coffee-utils",
|
3
3
|
"type": "module",
|
4
|
-
"version": "10.0.
|
4
|
+
"version": "10.0.4",
|
5
5
|
"description": "A set of utility functions for CoffeeScript",
|
6
6
|
"main": "coffee_utils.js",
|
7
7
|
"exports": {
|
@@ -12,6 +12,7 @@
|
|
12
12
|
"./log": "./src/log_utils.js",
|
13
13
|
"./block": "./src/block_utils.js",
|
14
14
|
"./indent": "./src/indent_utils.js",
|
15
|
+
"./html": "./src/html_utils.js",
|
15
16
|
"./stack": "./src/call_stack.js",
|
16
17
|
"./debug": "./src/debug_utils.js",
|
17
18
|
"./arrow": "./src/arrow.js",
|
package/src/SectionMap.coffee
CHANGED
@@ -97,33 +97,41 @@ export class SectionMap
|
|
97
97
|
hReplacers = desc
|
98
98
|
desc = @lSectionTree
|
99
99
|
else if notdefined(desc)
|
100
|
+
debug "desc is entire tree"
|
100
101
|
desc = @lSectionTree
|
101
102
|
|
102
103
|
if isArray(desc)
|
104
|
+
debug "item is an array"
|
103
105
|
lBlocks = []
|
104
106
|
setName = undef
|
105
107
|
for item in desc
|
106
108
|
subBlock = undef
|
107
|
-
if
|
108
|
-
|
109
|
-
else if isSectionName(item)
|
110
|
-
subBlock = @getBlock(item, hReplacers)
|
111
|
-
else if isSetName(item)
|
109
|
+
if isSetName(item)
|
110
|
+
debug "set name is #{item}"
|
112
111
|
setName = item
|
113
|
-
else if
|
114
|
-
subBlock = item
|
112
|
+
else if isSectionName(item) || isArray(item)
|
113
|
+
subBlock = @getBlock(item, hReplacers)
|
114
|
+
if defined(subBlock)
|
115
|
+
debug "add subBlock", subBlock
|
116
|
+
lBlocks.push subBlock
|
117
|
+
else
|
118
|
+
debug "subBlock is undef"
|
119
|
+
else if isString(item) && nonEmpty(item)
|
120
|
+
debug "add string", item
|
121
|
+
lBlocks.push item
|
115
122
|
else
|
116
123
|
croak "Bad item: #{OL(item)}"
|
117
|
-
|
118
|
-
lBlocks.push subBlock
|
124
|
+
|
119
125
|
block = arrayToBlock(lBlocks)
|
126
|
+
debug "block is", block
|
120
127
|
if defined(setName)
|
121
128
|
if defined(proc = hReplacers[setName])
|
122
|
-
debug "REPLACE #{setName}"
|
123
129
|
block = proc(block)
|
130
|
+
debug "REPLACE #{setName} with", block
|
124
131
|
else
|
125
132
|
debug "NO REPLACER for #{setName}"
|
126
133
|
else if isSectionName(desc)
|
134
|
+
debug "item is a section name"
|
127
135
|
block = @section(desc).getBlock()
|
128
136
|
if defined(proc = hReplacers[desc])
|
129
137
|
debug "REPLACE #{desc}"
|
@@ -131,7 +139,7 @@ export class SectionMap
|
|
131
139
|
else
|
132
140
|
debug "NO REPLACER for #{desc}"
|
133
141
|
else if isSetName(desc)
|
134
|
-
|
142
|
+
debug "item is a set name"
|
135
143
|
block = @getBlock(@hSets[desc], hReplacers)
|
136
144
|
else
|
137
145
|
croak "Bad 1st arg: #{OL(desc)}"
|
package/src/SectionMap.js
CHANGED
@@ -126,39 +126,46 @@ export var SectionMap = class SectionMap {
|
|
126
126
|
hReplacers = desc;
|
127
127
|
desc = this.lSectionTree;
|
128
128
|
} else if (notdefined(desc)) {
|
129
|
+
debug("desc is entire tree");
|
129
130
|
desc = this.lSectionTree;
|
130
131
|
}
|
131
132
|
if (isArray(desc)) {
|
133
|
+
debug("item is an array");
|
132
134
|
lBlocks = [];
|
133
135
|
setName = undef;
|
134
136
|
for (i = 0, len = desc.length; i < len; i++) {
|
135
137
|
item = desc[i];
|
136
138
|
subBlock = undef;
|
137
|
-
if (
|
138
|
-
|
139
|
-
} else if (isSectionName(item)) {
|
140
|
-
subBlock = this.getBlock(item, hReplacers);
|
141
|
-
} else if (isSetName(item)) {
|
139
|
+
if (isSetName(item)) {
|
140
|
+
debug(`set name is ${item}`);
|
142
141
|
setName = item;
|
143
|
-
} else if (
|
144
|
-
subBlock = item;
|
142
|
+
} else if (isSectionName(item) || isArray(item)) {
|
143
|
+
subBlock = this.getBlock(item, hReplacers);
|
144
|
+
if (defined(subBlock)) {
|
145
|
+
debug("add subBlock", subBlock);
|
146
|
+
lBlocks.push(subBlock);
|
147
|
+
} else {
|
148
|
+
debug("subBlock is undef");
|
149
|
+
}
|
150
|
+
} else if (isString(item) && nonEmpty(item)) {
|
151
|
+
debug("add string", item);
|
152
|
+
lBlocks.push(item);
|
145
153
|
} else {
|
146
154
|
croak(`Bad item: ${OL(item)}`);
|
147
155
|
}
|
148
|
-
if (defined(subBlock)) {
|
149
|
-
lBlocks.push(subBlock);
|
150
|
-
}
|
151
156
|
}
|
152
157
|
block = arrayToBlock(lBlocks);
|
158
|
+
debug("block is", block);
|
153
159
|
if (defined(setName)) {
|
154
160
|
if (defined(proc = hReplacers[setName])) {
|
155
|
-
debug(`REPLACE ${setName}`);
|
156
161
|
block = proc(block);
|
162
|
+
debug(`REPLACE ${setName} with`, block);
|
157
163
|
} else {
|
158
164
|
debug(`NO REPLACER for ${setName}`);
|
159
165
|
}
|
160
166
|
}
|
161
167
|
} else if (isSectionName(desc)) {
|
168
|
+
debug("item is a section name");
|
162
169
|
block = this.section(desc).getBlock();
|
163
170
|
if (defined(proc = hReplacers[desc])) {
|
164
171
|
debug(`REPLACE ${desc}`);
|
@@ -167,7 +174,7 @@ export var SectionMap = class SectionMap {
|
|
167
174
|
debug(`NO REPLACER for ${desc}`);
|
168
175
|
}
|
169
176
|
} else if (isSetName(desc)) {
|
170
|
-
|
177
|
+
debug("item is a set name");
|
171
178
|
block = this.getBlock(this.hSets[desc], hReplacers);
|
172
179
|
} else {
|
173
180
|
croak(`Bad 1st arg: ${OL(desc)}`);
|
package/src/block_utils.coffee
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
import fs from 'fs'
|
4
4
|
import readline from 'readline'
|
5
5
|
|
6
|
-
import {assert, error} from '@jdeighan/unit-tester/utils'
|
6
|
+
import {assert, error, croak} from '@jdeighan/unit-tester/utils'
|
7
7
|
import {
|
8
8
|
undef, defined, isEmpty, isString, isArray, nonEmpty, rtrim,
|
9
9
|
} from '@jdeighan/coffee-utils'
|
package/src/block_utils.js
CHANGED
@@ -0,0 +1,217 @@
|
|
1
|
+
# html_utils.coffee
|
2
|
+
|
3
|
+
import {assert, croak} from '@jdeighan/unit-tester/utils'
|
4
|
+
import {
|
5
|
+
undef, pass, words, isEmpty, nonEmpty,
|
6
|
+
} from '@jdeighan/coffee-utils'
|
7
|
+
import {indented, enclose} from '@jdeighan/coffee-utils/indent'
|
8
|
+
import {arrayToBlock} from '@jdeighan/coffee-utils/block'
|
9
|
+
import {debug} from '@jdeighan/coffee-utils/debug'
|
10
|
+
|
11
|
+
hNoEnd = {}
|
12
|
+
for tagName in words('area base br col command embed hr img input' \
|
13
|
+
+ ' keygen link meta param source track wbr')
|
14
|
+
hNoEnd[tagName] = true
|
15
|
+
|
16
|
+
# ---------------------------------------------------------------------------
|
17
|
+
|
18
|
+
export parsetag = (line) ->
|
19
|
+
|
20
|
+
if lMatches = line.match(///^
|
21
|
+
(?:
|
22
|
+
([A-Za-z][A-Za-z0-9_]*) # variable name
|
23
|
+
\s*
|
24
|
+
=
|
25
|
+
\s*
|
26
|
+
)? # variable is optional
|
27
|
+
([A-Za-z][A-Za-z0-9_]*) # tag name
|
28
|
+
(?:
|
29
|
+
\:
|
30
|
+
( [a-z]+ )
|
31
|
+
)?
|
32
|
+
(\S*) # modifiers (class names, etc.)
|
33
|
+
\s*
|
34
|
+
(.*) # attributes & enclosed text
|
35
|
+
$///)
|
36
|
+
[_, varName, tagName, subtype, modifiers, rest] = lMatches
|
37
|
+
else
|
38
|
+
croak "parsetag(): Invalid HTML: '#{line}'"
|
39
|
+
|
40
|
+
# --- Handle classes - subtypes and added via .<class>
|
41
|
+
lClasses = []
|
42
|
+
if nonEmpty(subtype) && (tagName != 'svelte')
|
43
|
+
lClasses.push subtype
|
44
|
+
|
45
|
+
if modifiers
|
46
|
+
# --- currently, these are only class names
|
47
|
+
while lMatches = modifiers.match(///^
|
48
|
+
\. ([A-Za-z][A-Za-z0-9_]*)
|
49
|
+
///)
|
50
|
+
[all, className] = lMatches
|
51
|
+
lClasses.push className
|
52
|
+
modifiers = modifiers.substring(all.length)
|
53
|
+
if modifiers
|
54
|
+
croak "parsetag(): Invalid modifiers in '#{line}'"
|
55
|
+
|
56
|
+
# --- Handle attributes
|
57
|
+
hAttr = {} # { name: { value: <value>, quote: <quote> }, ... }
|
58
|
+
|
59
|
+
if varName
|
60
|
+
hAttr['bind:this'] = {value: varName, quote: '{'}
|
61
|
+
|
62
|
+
if (tagName == 'script') && (subtype == 'startup')
|
63
|
+
hAttr['context'] = {value: 'module', quote: '"'}
|
64
|
+
|
65
|
+
if rest
|
66
|
+
while lMatches = rest.match(///^
|
67
|
+
(?:
|
68
|
+
(?:
|
69
|
+
(?:
|
70
|
+
( bind | on ) # prefix
|
71
|
+
:
|
72
|
+
)?
|
73
|
+
([A-Za-z][A-Za-z0-9_]*) # attribute name
|
74
|
+
)
|
75
|
+
=
|
76
|
+
(?:
|
77
|
+
\{ ([^}]*) \} # attribute value
|
78
|
+
| " ([^"]*) "
|
79
|
+
| ' ([^']*) '
|
80
|
+
| ([^"'\s]+)
|
81
|
+
)
|
82
|
+
|
|
83
|
+
\{
|
84
|
+
([A-Za-z][A-Za-z0-9_]*)
|
85
|
+
\}
|
86
|
+
) \s*
|
87
|
+
///)
|
88
|
+
[all, prefix, attrName, br_val, dq_val, sq_val, uq_val, ident] = lMatches
|
89
|
+
if ident
|
90
|
+
hAttr[ident] = { value: ident, shorthand: true }
|
91
|
+
else
|
92
|
+
if br_val
|
93
|
+
value = br_val
|
94
|
+
quote = '{'
|
95
|
+
else
|
96
|
+
assert ! prefix?, "prefix requires use of {...}"
|
97
|
+
if dq_val
|
98
|
+
value = dq_val
|
99
|
+
quote = '"'
|
100
|
+
else if sq_val
|
101
|
+
value = sq_val
|
102
|
+
quote = "'"
|
103
|
+
else
|
104
|
+
value = uq_val
|
105
|
+
quote = ''
|
106
|
+
|
107
|
+
if prefix
|
108
|
+
attrName = "#{prefix}:#{attrName}"
|
109
|
+
|
110
|
+
if attrName == 'class'
|
111
|
+
for className in value.split(/\s+/)
|
112
|
+
lClasses.push className
|
113
|
+
else
|
114
|
+
if hAttr.attrName?
|
115
|
+
croak "parsetag(): Multiple attributes named '#{attrName}'"
|
116
|
+
hAttr[attrName] = { value, quote }
|
117
|
+
|
118
|
+
rest = rest.substring(all.length)
|
119
|
+
|
120
|
+
# --- The rest is contained text
|
121
|
+
rest = rest.trim()
|
122
|
+
if lMatches = rest.match(///^
|
123
|
+
['"]
|
124
|
+
(.*)
|
125
|
+
['"]
|
126
|
+
$///)
|
127
|
+
rest = lMatches[1]
|
128
|
+
|
129
|
+
# --- Add class attribute to hAttr if there are classes
|
130
|
+
if (lClasses.length > 0)
|
131
|
+
hAttr.class = {
|
132
|
+
value: lClasses.join(' '),
|
133
|
+
quote: '"',
|
134
|
+
}
|
135
|
+
|
136
|
+
# --- Build the return value
|
137
|
+
hToken = {
|
138
|
+
type: 'tag'
|
139
|
+
tagName
|
140
|
+
}
|
141
|
+
|
142
|
+
if subtype
|
143
|
+
hToken.subtype = subtype
|
144
|
+
hToken.orgtag = "#{tagName}:#{subtype}"
|
145
|
+
else
|
146
|
+
hToken.orgtag = tagName
|
147
|
+
|
148
|
+
# --- if tagName == 'svelte', set hToken.tagName to hToken.orgtag
|
149
|
+
if (tagName == 'svelte')
|
150
|
+
hToken.tagName = hToken.orgtag
|
151
|
+
|
152
|
+
if nonEmpty(hAttr)
|
153
|
+
hToken.hAttr = hAttr
|
154
|
+
|
155
|
+
# --- Is there contained text?
|
156
|
+
if rest
|
157
|
+
hToken.text = rest
|
158
|
+
|
159
|
+
return hToken
|
160
|
+
|
161
|
+
# ---------------------------------------------------------------------------
|
162
|
+
# --- export only for unit testing
|
163
|
+
|
164
|
+
export attrStr = (hAttr) ->
|
165
|
+
|
166
|
+
if ! hAttr
|
167
|
+
return ''
|
168
|
+
str = ''
|
169
|
+
for attrName in Object.getOwnPropertyNames(hAttr)
|
170
|
+
{value, quote, shorthand} = hAttr[attrName]
|
171
|
+
if shorthand
|
172
|
+
str += " {#{value}}"
|
173
|
+
else
|
174
|
+
if quote == '{'
|
175
|
+
bquote = '{'
|
176
|
+
equote = '}'
|
177
|
+
else
|
178
|
+
bquote = equote = quote
|
179
|
+
str += " #{attrName}=#{bquote}#{value}#{equote}"
|
180
|
+
return str
|
181
|
+
|
182
|
+
# ---------------------------------------------------------------------------
|
183
|
+
|
184
|
+
export tag2str = (hToken, type='begin') ->
|
185
|
+
|
186
|
+
{tagName, hAttr} = hToken
|
187
|
+
if (type == 'begin')
|
188
|
+
str = "<#{tagName}" # build the string bit by bit
|
189
|
+
if nonEmpty(hAttr)
|
190
|
+
str += attrStr(hAttr)
|
191
|
+
str += '>'
|
192
|
+
return str
|
193
|
+
else if (type == 'end')
|
194
|
+
if hNoEnd[tagName]
|
195
|
+
return undef
|
196
|
+
else
|
197
|
+
return "</#{tagName}>"
|
198
|
+
else
|
199
|
+
croak "type must be 'begin' or 'end'"
|
200
|
+
|
201
|
+
# ---------------------------------------------------------------------------
|
202
|
+
# elem - indent text, surround with HTML tags
|
203
|
+
|
204
|
+
export elem = (tagName, hAttr=undef, text=undef, oneIndent="\t") ->
|
205
|
+
|
206
|
+
if isEmpty(text)
|
207
|
+
return undef
|
208
|
+
hToken = {
|
209
|
+
tagName
|
210
|
+
hAttr
|
211
|
+
text
|
212
|
+
}
|
213
|
+
return arrayToBlock([
|
214
|
+
tag2str(hToken, 'begin')
|
215
|
+
indented(text, 1, oneIndent)
|
216
|
+
tag2str(hToken, 'end')
|
217
|
+
])
|
@@ -0,0 +1,222 @@
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
2
|
+
// html_utils.coffee
|
3
|
+
var hNoEnd, i, len, ref, tagName;
|
4
|
+
|
5
|
+
import {
|
6
|
+
assert,
|
7
|
+
croak
|
8
|
+
} from '@jdeighan/unit-tester/utils';
|
9
|
+
|
10
|
+
import {
|
11
|
+
undef,
|
12
|
+
pass,
|
13
|
+
words,
|
14
|
+
isEmpty,
|
15
|
+
nonEmpty
|
16
|
+
} from '@jdeighan/coffee-utils';
|
17
|
+
|
18
|
+
import {
|
19
|
+
indented,
|
20
|
+
enclose
|
21
|
+
} from '@jdeighan/coffee-utils/indent';
|
22
|
+
|
23
|
+
import {
|
24
|
+
arrayToBlock
|
25
|
+
} from '@jdeighan/coffee-utils/block';
|
26
|
+
|
27
|
+
import {
|
28
|
+
debug
|
29
|
+
} from '@jdeighan/coffee-utils/debug';
|
30
|
+
|
31
|
+
hNoEnd = {};
|
32
|
+
|
33
|
+
ref = words('area base br col command embed hr img input' + ' keygen link meta param source track wbr');
|
34
|
+
for (i = 0, len = ref.length; i < len; i++) {
|
35
|
+
tagName = ref[i];
|
36
|
+
hNoEnd[tagName] = true;
|
37
|
+
}
|
38
|
+
|
39
|
+
// ---------------------------------------------------------------------------
|
40
|
+
export var parsetag = function(line) {
|
41
|
+
var _, all, attrName, br_val, className, dq_val, hAttr, hToken, ident, j, lClasses, lMatches, len1, modifiers, prefix, quote, ref1, rest, sq_val, subtype, uq_val, value, varName;
|
42
|
+
if (lMatches = line.match(/^(?:([A-Za-z][A-Za-z0-9_]*)\s*=\s*)?([A-Za-z][A-Za-z0-9_]*)(?:\:([a-z]+))?(\S*)\s*(.*)$/)) { // variable name
|
43
|
+
// variable is optional
|
44
|
+
// tag name
|
45
|
+
// modifiers (class names, etc.)
|
46
|
+
// attributes & enclosed text
|
47
|
+
[_, varName, tagName, subtype, modifiers, rest] = lMatches;
|
48
|
+
} else {
|
49
|
+
croak(`parsetag(): Invalid HTML: '${line}'`);
|
50
|
+
}
|
51
|
+
// --- Handle classes - subtypes and added via .<class>
|
52
|
+
lClasses = [];
|
53
|
+
if (nonEmpty(subtype) && (tagName !== 'svelte')) {
|
54
|
+
lClasses.push(subtype);
|
55
|
+
}
|
56
|
+
if (modifiers) {
|
57
|
+
// --- currently, these are only class names
|
58
|
+
while (lMatches = modifiers.match(/^\.([A-Za-z][A-Za-z0-9_]*)/)) {
|
59
|
+
[all, className] = lMatches;
|
60
|
+
lClasses.push(className);
|
61
|
+
modifiers = modifiers.substring(all.length);
|
62
|
+
}
|
63
|
+
if (modifiers) {
|
64
|
+
croak(`parsetag(): Invalid modifiers in '${line}'`);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
// --- Handle attributes
|
68
|
+
hAttr = {}; // { name: { value: <value>, quote: <quote> }, ... }
|
69
|
+
if (varName) {
|
70
|
+
hAttr['bind:this'] = {
|
71
|
+
value: varName,
|
72
|
+
quote: '{'
|
73
|
+
};
|
74
|
+
}
|
75
|
+
if ((tagName === 'script') && (subtype === 'startup')) {
|
76
|
+
hAttr['context'] = {
|
77
|
+
value: 'module',
|
78
|
+
quote: '"'
|
79
|
+
};
|
80
|
+
}
|
81
|
+
if (rest) {
|
82
|
+
while (lMatches = rest.match(/^(?:(?:(?:(bind|on):)?([A-Za-z][A-Za-z0-9_]*))=(?:\{([^}]*)\}|"([^"]*)"|'([^']*)'|([^"'\s]+))|\{([A-Za-z][A-Za-z0-9_]*)\})\s*/)) { // prefix
|
83
|
+
// attribute name
|
84
|
+
// attribute value
|
85
|
+
[all, prefix, attrName, br_val, dq_val, sq_val, uq_val, ident] = lMatches;
|
86
|
+
if (ident) {
|
87
|
+
hAttr[ident] = {
|
88
|
+
value: ident,
|
89
|
+
shorthand: true
|
90
|
+
};
|
91
|
+
} else {
|
92
|
+
if (br_val) {
|
93
|
+
value = br_val;
|
94
|
+
quote = '{';
|
95
|
+
} else {
|
96
|
+
assert(prefix == null, "prefix requires use of {...}");
|
97
|
+
if (dq_val) {
|
98
|
+
value = dq_val;
|
99
|
+
quote = '"';
|
100
|
+
} else if (sq_val) {
|
101
|
+
value = sq_val;
|
102
|
+
quote = "'";
|
103
|
+
} else {
|
104
|
+
value = uq_val;
|
105
|
+
quote = '';
|
106
|
+
}
|
107
|
+
}
|
108
|
+
if (prefix) {
|
109
|
+
attrName = `${prefix}:${attrName}`;
|
110
|
+
}
|
111
|
+
if (attrName === 'class') {
|
112
|
+
ref1 = value.split(/\s+/);
|
113
|
+
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
114
|
+
className = ref1[j];
|
115
|
+
lClasses.push(className);
|
116
|
+
}
|
117
|
+
} else {
|
118
|
+
if (hAttr.attrName != null) {
|
119
|
+
croak(`parsetag(): Multiple attributes named '${attrName}'`);
|
120
|
+
}
|
121
|
+
hAttr[attrName] = {value, quote};
|
122
|
+
}
|
123
|
+
}
|
124
|
+
rest = rest.substring(all.length);
|
125
|
+
}
|
126
|
+
}
|
127
|
+
// --- The rest is contained text
|
128
|
+
rest = rest.trim();
|
129
|
+
if (lMatches = rest.match(/^['"](.*)['"]$/)) {
|
130
|
+
rest = lMatches[1];
|
131
|
+
}
|
132
|
+
// --- Add class attribute to hAttr if there are classes
|
133
|
+
if (lClasses.length > 0) {
|
134
|
+
hAttr.class = {
|
135
|
+
value: lClasses.join(' '),
|
136
|
+
quote: '"'
|
137
|
+
};
|
138
|
+
}
|
139
|
+
// --- Build the return value
|
140
|
+
hToken = {
|
141
|
+
type: 'tag',
|
142
|
+
tagName
|
143
|
+
};
|
144
|
+
if (subtype) {
|
145
|
+
hToken.subtype = subtype;
|
146
|
+
hToken.orgtag = `${tagName}:${subtype}`;
|
147
|
+
} else {
|
148
|
+
hToken.orgtag = tagName;
|
149
|
+
}
|
150
|
+
// --- if tagName == 'svelte', set hToken.tagName to hToken.orgtag
|
151
|
+
if (tagName === 'svelte') {
|
152
|
+
hToken.tagName = hToken.orgtag;
|
153
|
+
}
|
154
|
+
if (nonEmpty(hAttr)) {
|
155
|
+
hToken.hAttr = hAttr;
|
156
|
+
}
|
157
|
+
// --- Is there contained text?
|
158
|
+
if (rest) {
|
159
|
+
hToken.text = rest;
|
160
|
+
}
|
161
|
+
return hToken;
|
162
|
+
};
|
163
|
+
|
164
|
+
// ---------------------------------------------------------------------------
|
165
|
+
// --- export only for unit testing
|
166
|
+
export var attrStr = function(hAttr) {
|
167
|
+
var attrName, bquote, equote, j, len1, quote, ref1, shorthand, str, value;
|
168
|
+
if (!hAttr) {
|
169
|
+
return '';
|
170
|
+
}
|
171
|
+
str = '';
|
172
|
+
ref1 = Object.getOwnPropertyNames(hAttr);
|
173
|
+
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
174
|
+
attrName = ref1[j];
|
175
|
+
({value, quote, shorthand} = hAttr[attrName]);
|
176
|
+
if (shorthand) {
|
177
|
+
str += ` {${value}}`;
|
178
|
+
} else {
|
179
|
+
if (quote === '{') {
|
180
|
+
bquote = '{';
|
181
|
+
equote = '}';
|
182
|
+
} else {
|
183
|
+
bquote = equote = quote;
|
184
|
+
}
|
185
|
+
str += ` ${attrName}=${bquote}${value}${equote}`;
|
186
|
+
}
|
187
|
+
}
|
188
|
+
return str;
|
189
|
+
};
|
190
|
+
|
191
|
+
// ---------------------------------------------------------------------------
|
192
|
+
export var tag2str = function(hToken, type = 'begin') {
|
193
|
+
var hAttr, str;
|
194
|
+
({tagName, hAttr} = hToken);
|
195
|
+
if (type === 'begin') {
|
196
|
+
str = `<${tagName}`;
|
197
|
+
if (nonEmpty(hAttr)) {
|
198
|
+
str += attrStr(hAttr);
|
199
|
+
}
|
200
|
+
str += '>';
|
201
|
+
return str;
|
202
|
+
} else if (type === 'end') {
|
203
|
+
if (hNoEnd[tagName]) {
|
204
|
+
return undef;
|
205
|
+
} else {
|
206
|
+
return `</${tagName}>`;
|
207
|
+
}
|
208
|
+
} else {
|
209
|
+
return croak("type must be 'begin' or 'end'");
|
210
|
+
}
|
211
|
+
};
|
212
|
+
|
213
|
+
// ---------------------------------------------------------------------------
|
214
|
+
// elem - indent text, surround with HTML tags
|
215
|
+
export var elem = function(tagName, hAttr = undef, text = undef, oneIndent = "\t") {
|
216
|
+
var hToken;
|
217
|
+
if (isEmpty(text)) {
|
218
|
+
return undef;
|
219
|
+
}
|
220
|
+
hToken = {tagName, hAttr, text};
|
221
|
+
return arrayToBlock([tag2str(hToken, 'begin'), indented(text, 1, oneIndent), tag2str(hToken, 'end')]);
|
222
|
+
};
|
package/src/indent_utils.coffee
CHANGED
@@ -164,14 +164,3 @@ export enclose = (text, pre, post, oneIndent="\t") ->
|
|
164
164
|
indented(text, 1, oneIndent)
|
165
165
|
post
|
166
166
|
])
|
167
|
-
|
168
|
-
# ---------------------------------------------------------------------------
|
169
|
-
# elem - indent text, surround with HTML tags
|
170
|
-
|
171
|
-
export elem = (text, tag, oneIndent="\t") ->
|
172
|
-
|
173
|
-
return arrayToBlock([
|
174
|
-
"<#{tag}>"
|
175
|
-
indented(text, 1, oneIndent)
|
176
|
-
"</#{tag}>"
|
177
|
-
])
|
package/src/indent_utils.js
CHANGED
@@ -187,9 +187,3 @@ export var untabify = function(str, numSpaces = 3) {
|
|
187
187
|
export var enclose = function(text, pre, post, oneIndent = "\t") {
|
188
188
|
return arrayToBlock([pre, indented(text, 1, oneIndent), post]);
|
189
189
|
};
|
190
|
-
|
191
|
-
// ---------------------------------------------------------------------------
|
192
|
-
// elem - indent text, surround with HTML tags
|
193
|
-
export var elem = function(text, tag, oneIndent = "\t") {
|
194
|
-
return arrayToBlock([`<${tag}>`, indented(text, 1, oneIndent), `</${tag}>`]);
|
195
|
-
};
|
package/src/log_utils.coffee
CHANGED
@@ -183,7 +183,12 @@ export logItem = (label, item, pre='', itemPre=undef) ->
|
|
183
183
|
putstr "#{pre}#{labelStr}#{item}"
|
184
184
|
else if isString(item)
|
185
185
|
if (item.length <= maxOneLine)
|
186
|
-
|
186
|
+
result = escapeStr(item)
|
187
|
+
hasApos = (result.indexOf("'") >= 0)
|
188
|
+
if hasApos
|
189
|
+
putstr "#{pre}#{labelStr}\"#{result}\""
|
190
|
+
else
|
191
|
+
putstr "#{pre}#{labelStr}'#{result}'"
|
187
192
|
else
|
188
193
|
if label
|
189
194
|
putstr "#{pre}#{label}:"
|
package/src/log_utils.js
CHANGED
@@ -184,7 +184,7 @@ export var logBareItem = function(item, pre = '') {
|
|
184
184
|
|
185
185
|
// ---------------------------------------------------------------------------
|
186
186
|
export var logItem = function(label, item, pre = '', itemPre = undef) {
|
187
|
-
var i, labelStr, len, ref, str;
|
187
|
+
var hasApos, i, labelStr, len, ref, result, str;
|
188
188
|
assert(isString(pre), `not a string: ${OL(pre)}`);
|
189
189
|
assert(isFunction(putstr), "putstr not properly set");
|
190
190
|
assert(!label || isString(label), "label a non-string");
|
@@ -207,7 +207,13 @@ export var logItem = function(label, item, pre = '', itemPre = undef) {
|
|
207
207
|
putstr(`${pre}${labelStr}${item}`);
|
208
208
|
} else if (isString(item)) {
|
209
209
|
if (item.length <= maxOneLine) {
|
210
|
-
|
210
|
+
result = escapeStr(item);
|
211
|
+
hasApos = result.indexOf("'") >= 0;
|
212
|
+
if (hasApos) {
|
213
|
+
putstr(`${pre}${labelStr}\"${result}\"`);
|
214
|
+
} else {
|
215
|
+
putstr(`${pre}${labelStr}'${result}'`);
|
216
|
+
}
|
211
217
|
} else {
|
212
218
|
if (label) {
|
213
219
|
putstr(`${pre}${label}:`);
|