@jdeighan/coffee-utils 11.0.30 → 11.0.32
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +4 -6
- package/src/Section.coffee +10 -25
- package/src/Section.js +14 -35
- package/src/SectionMap.coffee +160 -110
- package/src/SectionMap.js +190 -137
- package/src/block.coffee +2 -1
- package/src/block.js +1 -1
- package/src/fs.coffee +3 -1
- package/src/fs.js +3 -0
- package/src/utils.coffee +8 -3
- package/src/utils.js +11 -4
- package/src/placeholders.coffee +0 -26
- package/src/placeholders.js +0 -34
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@jdeighan/coffee-utils",
|
3
3
|
"type": "module",
|
4
|
-
"version": "11.0.
|
4
|
+
"version": "11.0.32",
|
5
5
|
"description": "A set of utility functions for CoffeeScript",
|
6
6
|
"main": "coffee_utils.js",
|
7
7
|
"exports": {
|
@@ -19,7 +19,6 @@
|
|
19
19
|
"./svelte": "./src/svelte.js",
|
20
20
|
"./store": "./src/DataStores.js",
|
21
21
|
"./taml": "./src/taml.js",
|
22
|
-
"./placeholders": "./src/placeholders.js",
|
23
22
|
"./section": "./src/Section.js",
|
24
23
|
"./sectionmap": "./src/SectionMap.js",
|
25
24
|
"./fsa": "./src/fsa.js",
|
@@ -32,8 +31,7 @@
|
|
32
31
|
"verbose": false
|
33
32
|
},
|
34
33
|
"scripts": {
|
35
|
-
"build": "cls &&
|
36
|
-
"pretest": "cls && cielo -qfc ./test && coffee -c .",
|
34
|
+
"build": "cls && coffee -c .",
|
37
35
|
"test": "npm run build && ava ./test/*.test.js && git status"
|
38
36
|
},
|
39
37
|
"repository": {
|
@@ -50,7 +48,7 @@
|
|
50
48
|
},
|
51
49
|
"homepage": "https://github.com/johndeighan/coffee-utils#readme",
|
52
50
|
"dependencies": {
|
53
|
-
"@jdeighan/exceptions": "^1.0.
|
51
|
+
"@jdeighan/exceptions": "^1.0.26",
|
54
52
|
"cross-env": "^7.0.3",
|
55
53
|
"js-yaml": "^4.1.0",
|
56
54
|
"n-readlines": "^1.0.1",
|
@@ -58,6 +56,6 @@
|
|
58
56
|
"svelte": "^3.52.0"
|
59
57
|
},
|
60
58
|
"devDependencies": {
|
61
|
-
"@jdeighan/unit-tester": "^2.0.
|
59
|
+
"@jdeighan/unit-tester": "^2.0.52"
|
62
60
|
}
|
63
61
|
}
|
package/src/Section.coffee
CHANGED
@@ -3,36 +3,20 @@
|
|
3
3
|
import {assert, croak} from '@jdeighan/exceptions'
|
4
4
|
import {debug} from '@jdeighan/exceptions/debug'
|
5
5
|
import {
|
6
|
-
pass, undef, defined, isArray, isEmpty,
|
6
|
+
pass, undef, defined, isArray, isEmpty, isFunction,
|
7
7
|
} from '@jdeighan/coffee-utils'
|
8
|
-
import {
|
9
|
-
import {indented} from '@jdeighan/coffee-utils/indent'
|
8
|
+
import {toBlock} from '@jdeighan/coffee-utils/block'
|
10
9
|
|
11
10
|
# ---------------------------------------------------------------------------
|
12
11
|
|
13
12
|
export class Section
|
14
13
|
|
15
|
-
constructor: (@name,
|
14
|
+
constructor: (@name, @replacer=undef) ->
|
16
15
|
# --- name can be undef or empty
|
17
16
|
|
18
17
|
@lParts = []
|
19
|
-
if defined(
|
20
|
-
@
|
21
|
-
|
22
|
-
# ..........................................................
|
23
|
-
|
24
|
-
length: () ->
|
25
|
-
|
26
|
-
return @lParts.length
|
27
|
-
|
28
|
-
# ..........................................................
|
29
|
-
|
30
|
-
indent: (level=1, oneIndent="\t") ->
|
31
|
-
|
32
|
-
lNewLines = for line in @lParts
|
33
|
-
indented(line, level, oneIndent)
|
34
|
-
@lParts = lNewLines
|
35
|
-
return
|
18
|
+
if defined(@replacer)
|
19
|
+
assert isFunction(@replacer), "bad replacer"
|
36
20
|
|
37
21
|
# ..........................................................
|
38
22
|
|
@@ -81,7 +65,8 @@ export class Section
|
|
81
65
|
if (@lParts.length == 0)
|
82
66
|
debug "return undef from Section.getBlock()"
|
83
67
|
return undef
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
68
|
+
block = toBlock(@lParts)
|
69
|
+
if defined(@replacer)
|
70
|
+
block = @replacer block
|
71
|
+
debug "return from Section.getBlock()", block
|
72
|
+
return block
|
package/src/Section.js
CHANGED
@@ -14,49 +14,26 @@ import {
|
|
14
14
|
undef,
|
15
15
|
defined,
|
16
16
|
isArray,
|
17
|
-
isEmpty
|
17
|
+
isEmpty,
|
18
|
+
isFunction
|
18
19
|
} from '@jdeighan/coffee-utils';
|
19
20
|
|
20
21
|
import {
|
21
|
-
|
22
|
+
toBlock
|
22
23
|
} from '@jdeighan/coffee-utils/block';
|
23
24
|
|
24
|
-
import {
|
25
|
-
indented
|
26
|
-
} from '@jdeighan/coffee-utils/indent';
|
27
|
-
|
28
25
|
// ---------------------------------------------------------------------------
|
29
26
|
export var Section = class Section {
|
30
|
-
constructor(name,
|
27
|
+
constructor(name, replacer = undef) {
|
31
28
|
this.name = name;
|
29
|
+
this.replacer = replacer;
|
32
30
|
// --- name can be undef or empty
|
33
31
|
this.lParts = [];
|
34
|
-
if (defined(
|
35
|
-
this.
|
32
|
+
if (defined(this.replacer)) {
|
33
|
+
assert(isFunction(this.replacer), "bad replacer");
|
36
34
|
}
|
37
35
|
}
|
38
36
|
|
39
|
-
// ..........................................................
|
40
|
-
length() {
|
41
|
-
return this.lParts.length;
|
42
|
-
}
|
43
|
-
|
44
|
-
// ..........................................................
|
45
|
-
indent(level = 1, oneIndent = "\t") {
|
46
|
-
var lNewLines, line;
|
47
|
-
lNewLines = (function() {
|
48
|
-
var i, len, ref, results;
|
49
|
-
ref = this.lParts;
|
50
|
-
results = [];
|
51
|
-
for (i = 0, len = ref.length; i < len; i++) {
|
52
|
-
line = ref[i];
|
53
|
-
results.push(indented(line, level, oneIndent));
|
54
|
-
}
|
55
|
-
return results;
|
56
|
-
}).call(this);
|
57
|
-
this.lParts = lNewLines;
|
58
|
-
}
|
59
|
-
|
60
37
|
// ..........................................................
|
61
38
|
isEmpty() {
|
62
39
|
return this.lParts.length === 0;
|
@@ -96,16 +73,18 @@ export var Section = class Section {
|
|
96
73
|
|
97
74
|
// ..........................................................
|
98
75
|
getBlock() {
|
99
|
-
var
|
76
|
+
var block;
|
100
77
|
debug("enter Section.getBlock()");
|
101
78
|
if (this.lParts.length === 0) {
|
102
79
|
debug("return undef from Section.getBlock()");
|
103
80
|
return undef;
|
104
|
-
} else {
|
105
|
-
result = arrayToBlock(this.lParts);
|
106
|
-
debug("return from Section.getBlock()", result);
|
107
|
-
return result;
|
108
81
|
}
|
82
|
+
block = toBlock(this.lParts);
|
83
|
+
if (defined(this.replacer)) {
|
84
|
+
block = this.replacer(block);
|
85
|
+
}
|
86
|
+
debug("return from Section.getBlock()", block);
|
87
|
+
return block;
|
109
88
|
}
|
110
89
|
|
111
90
|
};
|
package/src/SectionMap.coffee
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
# SectionMap.coffee
|
2
2
|
|
3
|
-
import {assert, croak} from '@jdeighan/exceptions'
|
4
|
-
import {LOG} from '@jdeighan/exceptions/log'
|
5
|
-
import {debug} from '@jdeighan/exceptions/debug'
|
6
3
|
import {
|
7
|
-
|
4
|
+
assert, croak, LOG, LOGVALUE, LOGTAML, debug, isTAML, fromTAML,
|
5
|
+
} from '@jdeighan/exceptions'
|
6
|
+
import {
|
7
|
+
pass, undef, def, notdef, OL, isEmpty, nonEmpty,
|
8
8
|
isString, isHash, isArray, isUniqueTree, isNonEmptyString,
|
9
|
-
isNonEmptyArray,
|
9
|
+
isNonEmptyArray, isFunction, jsType, isArrayOfStrings,
|
10
10
|
} from '@jdeighan/coffee-utils'
|
11
11
|
import {toBlock} from '@jdeighan/coffee-utils/block'
|
12
|
-
import {isTAML, fromTAML} from '@jdeighan/coffee-utils/taml'
|
13
12
|
import {Section} from '@jdeighan/coffee-utils/section'
|
14
13
|
|
15
14
|
# ---------------------------------------------------------------------------
|
@@ -28,142 +27,161 @@ isSetName = (name) ->
|
|
28
27
|
|
29
28
|
export class SectionMap
|
30
29
|
|
31
|
-
constructor: (@
|
32
|
-
# ---
|
33
|
-
|
34
|
-
|
30
|
+
constructor: (tree, @hReplacers={}) ->
|
31
|
+
# --- tree is a tree of section/set names
|
32
|
+
# or a TAML string that converts to one
|
33
|
+
# --- hReplacers are callbacks that are called
|
34
|
+
# when a set or section is processed
|
35
|
+
# should be <name> -> <function>
|
36
|
+
# <name> can be a section name or a set name
|
37
|
+
# <function> should be <block> -> <block>
|
35
38
|
|
36
|
-
|
37
|
-
@SectionTree = fromTAML(@lSectionTree)
|
39
|
+
debug "enter SectionMap()", tree, @hReplacers
|
38
40
|
|
39
|
-
|
41
|
+
@checkTree tree
|
42
|
+
@checkReplacers @hReplacers
|
40
43
|
|
41
|
-
# ---
|
42
|
-
@
|
44
|
+
@hSections = {} # --- {section name: Section Object}
|
45
|
+
@hSets = {ALL: @lFullTree} # --- {set name: array of parts}
|
43
46
|
|
44
|
-
|
45
|
-
@hSets = {}
|
47
|
+
@init @lFullTree
|
46
48
|
|
47
|
-
|
48
|
-
debug
|
49
|
+
debug 'hSections', @hSections
|
50
|
+
debug 'hSets', @hSets
|
51
|
+
debug "return from SectionMap()"
|
49
52
|
|
50
53
|
# ..........................................................
|
51
54
|
|
52
|
-
|
55
|
+
init: (lTree) ->
|
53
56
|
|
54
|
-
debug "enter
|
57
|
+
debug "enter init()", lTree
|
55
58
|
assert isArray(lTree), "not an array"
|
56
59
|
assert nonEmpty(lTree), "empty array"
|
57
60
|
|
58
61
|
firstItem = lTree[0]
|
59
62
|
if isSetName(firstItem)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
@hSections[item] = new Section(item)
|
75
|
-
else
|
76
|
-
croak "Bad section tree: #{OL(@lSectionTree)}"
|
77
|
-
debug "return from build()", @hSections, @hSets
|
63
|
+
debug "found set name #{OL(firstItem)}"
|
64
|
+
lTree = lTree.slice(1)
|
65
|
+
@mkSet firstItem, lTree
|
66
|
+
|
67
|
+
for item in lTree
|
68
|
+
if isArray(item)
|
69
|
+
debug "init subtree"
|
70
|
+
@init item
|
71
|
+
else if isSectionName(item)
|
72
|
+
debug "mkSection #{OL(item)}"
|
73
|
+
@mkSection item
|
74
|
+
else
|
75
|
+
assert isString(item), "Bad item in tree: #{OL(item)}"
|
76
|
+
debug "return from init()"
|
78
77
|
return
|
79
78
|
|
80
79
|
# ..........................................................
|
81
|
-
# --- hProc should be <name> -> <function>
|
82
|
-
# <name> can be a section name or a set name
|
83
|
-
# <function> should be <block> -> <block>
|
84
|
-
# --- desc can be:
|
85
|
-
# an array, which may begin with a set name
|
86
|
-
# a section name
|
87
|
-
# a set name
|
88
|
-
# undef (equivalent to being set to @SectionTree)
|
89
|
-
|
90
|
-
getBlock: (desc=undef, hReplacers={}) ->
|
91
|
-
|
92
|
-
debug "enter SectionMap.getBlock()", desc, hReplacers
|
93
|
-
|
94
|
-
# --- desc can only be a string or an array
|
95
|
-
# so, if it's a hash, then it's really the hReplacers
|
96
|
-
# and the real desc is undef
|
97
|
-
|
98
|
-
if isHash(desc)
|
99
|
-
debug "arg 1 is hReplacers, no desc"
|
100
|
-
assert isEmpty(hReplacers), "invalid parms"
|
101
|
-
hReplacers = desc
|
102
|
-
desc = @lSectionTree
|
103
|
-
else if notdefined(desc)
|
104
|
-
debug "desc is entire tree"
|
105
|
-
desc = @lSectionTree
|
106
|
-
|
107
|
-
if isArray(desc)
|
108
|
-
debug "item is an array"
|
109
|
-
lBlocks = []
|
110
|
-
setName = undef
|
111
|
-
for item in desc
|
112
|
-
subBlock = undef
|
113
|
-
if isSetName(item)
|
114
|
-
debug "set name is #{item}"
|
115
|
-
setName = item
|
116
|
-
else if isSectionName(item) || isArray(item)
|
117
|
-
subBlock = @getBlock(item, hReplacers)
|
118
|
-
if defined(subBlock)
|
119
|
-
debug "add subBlock", subBlock
|
120
|
-
lBlocks.push subBlock
|
121
|
-
else
|
122
|
-
debug "subBlock is undef"
|
123
|
-
else if isString(item) && nonEmpty(item)
|
124
|
-
debug "add string", item
|
125
|
-
lBlocks.push item
|
126
|
-
else
|
127
|
-
croak "Bad item: #{OL(item)}"
|
128
80
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
81
|
+
mkSet: (name, lTree) ->
|
82
|
+
|
83
|
+
assert isArray(lTree), "tree is not an array"
|
84
|
+
assert nonEmpty(lTree), "set without sections"
|
85
|
+
assert notdef(@hSets[name]), "set #{OL(name)} already exists"
|
86
|
+
@hSets[name] = lTree
|
87
|
+
return
|
88
|
+
|
89
|
+
# ..........................................................
|
90
|
+
|
91
|
+
mkSection: (name) ->
|
92
|
+
|
93
|
+
assert notdef(@hSections[name]), "duplicate section name"
|
94
|
+
@hSections[name] = new Section(name, @hReplacers[name])
|
95
|
+
return
|
96
|
+
|
97
|
+
# ..........................................................
|
98
|
+
|
99
|
+
getBlock: (desc='ALL') ->
|
100
|
+
# ..........................................................
|
101
|
+
# --- desc can be:
|
102
|
+
# a section name
|
103
|
+
# a set name
|
104
|
+
# an array of section or set names or literal strings
|
105
|
+
# i.e. it should NOT contain sub-arrays
|
106
|
+
|
107
|
+
if isString(desc)
|
108
|
+
debug "enter SectionMap.getBlock(#{OL(desc)})"
|
109
|
+
else if isArrayOfStrings(desc)
|
110
|
+
debug "enter SectionMap.getBlock()", desc
|
111
|
+
else
|
112
|
+
croak "Bad desc: #{OL(desc)}"
|
113
|
+
|
114
|
+
if isSectionName(desc)
|
138
115
|
debug "item is a section name"
|
116
|
+
# --- a section's getBlock() applies any replacer
|
139
117
|
block = @section(desc).getBlock()
|
140
|
-
if defined(proc = hReplacers[desc])
|
141
|
-
debug "REPLACE #{desc}"
|
142
|
-
block = proc(block)
|
143
|
-
else
|
144
|
-
debug "NO REPLACER for #{desc}"
|
145
118
|
else if isSetName(desc)
|
146
119
|
debug "item is a set name"
|
147
|
-
|
120
|
+
lBlocks = for item in @hSets[desc]
|
121
|
+
if isArray(item)
|
122
|
+
@getBlock item[0]
|
123
|
+
else if isString(item)
|
124
|
+
@getBlock item
|
125
|
+
else
|
126
|
+
croak "Item in set #{desc} is not a string or array"
|
127
|
+
block = toBlock(lBlocks)
|
128
|
+
replacer = @hReplacers[desc]
|
129
|
+
debug "replacer for is #{OL(replacer)}"
|
130
|
+
if def(replacer)
|
131
|
+
block = replacer(block)
|
132
|
+
else if isString(desc)
|
133
|
+
debug "item is a literal string"
|
134
|
+
# --- a literal string
|
135
|
+
block = desc
|
136
|
+
else if isArray(desc)
|
137
|
+
debug "item is an array"
|
138
|
+
lBlocks = for item in desc
|
139
|
+
@getBlock(item)
|
140
|
+
block = toBlock(lBlocks)
|
148
141
|
else
|
149
|
-
croak "Bad
|
142
|
+
croak "Bad arg: #{OL(desc)}"
|
143
|
+
|
150
144
|
debug "return from SectionMap.getBlock()", block
|
151
145
|
return block
|
152
146
|
|
147
|
+
# ..........................................................
|
148
|
+
# --- does NOT call any replacers, and skips literal strings
|
149
|
+
# so only useful for isEmpty() and nonEmpty()
|
150
|
+
|
151
|
+
allSections: (desc=undef) ->
|
152
|
+
|
153
|
+
debug "enter allSections()", desc
|
154
|
+
if notdef(desc)
|
155
|
+
desc = @lFullTree
|
156
|
+
|
157
|
+
if isSectionName(desc)
|
158
|
+
debug "is section name"
|
159
|
+
yield @section(desc)
|
160
|
+
else if isSetName(desc)
|
161
|
+
debug "is set name"
|
162
|
+
for name in @hSets[desc]
|
163
|
+
yield from @allSections(name)
|
164
|
+
else if isArray(desc)
|
165
|
+
debug "is array"
|
166
|
+
for item in desc
|
167
|
+
yield from @allSections(item)
|
168
|
+
debug "return from allSections()"
|
169
|
+
return
|
170
|
+
|
153
171
|
# ..........................................................
|
154
172
|
|
155
|
-
isEmpty: () ->
|
173
|
+
isEmpty: (desc=undef) ->
|
156
174
|
|
157
|
-
for
|
175
|
+
for sect from @allSections(desc)
|
158
176
|
if sect.nonEmpty()
|
159
177
|
return false
|
160
178
|
return true
|
161
179
|
|
162
180
|
# ..........................................................
|
163
181
|
|
164
|
-
nonEmpty: () ->
|
182
|
+
nonEmpty: (desc=undef) ->
|
165
183
|
|
166
|
-
for
|
184
|
+
for sect from @allSections(desc)
|
167
185
|
if sect.nonEmpty()
|
168
186
|
return true
|
169
187
|
return false
|
@@ -173,7 +191,7 @@ export class SectionMap
|
|
173
191
|
section: (name) ->
|
174
192
|
|
175
193
|
sect = @hSections[name]
|
176
|
-
assert
|
194
|
+
assert def(sect), "No section named #{OL(name)}"
|
177
195
|
return sect
|
178
196
|
|
179
197
|
# ..........................................................
|
@@ -182,8 +200,8 @@ export class SectionMap
|
|
182
200
|
|
183
201
|
assert isSetName(name), "bad set name #{OL(name)}"
|
184
202
|
lSubTree = @hSets[name]
|
185
|
-
assert
|
186
|
-
return @section(lSubTree[
|
203
|
+
assert def(lSubTree), "no such set #{OL(name)}"
|
204
|
+
return @section(lSubTree[0])
|
187
205
|
|
188
206
|
# ..........................................................
|
189
207
|
|
@@ -191,5 +209,37 @@ export class SectionMap
|
|
191
209
|
|
192
210
|
assert isSetName(name), "bad set name #{OL(name)}"
|
193
211
|
lSubTree = @hSets[name]
|
194
|
-
assert
|
212
|
+
assert def(lSubTree), "no such set #{OL(name)}"
|
195
213
|
return @section(lSubTree[lSubTree.length - 1])
|
214
|
+
|
215
|
+
# ..........................................................
|
216
|
+
|
217
|
+
checkTree: (tree) ->
|
218
|
+
|
219
|
+
debug "enter checkTree()"
|
220
|
+
if isString(tree)
|
221
|
+
debug "tree is a string"
|
222
|
+
assert isTAML(tree), "not TAML"
|
223
|
+
@lFullTree = fromTAML(tree)
|
224
|
+
else
|
225
|
+
@lFullTree = tree
|
226
|
+
|
227
|
+
assert isArray(@lFullTree), "not an array"
|
228
|
+
assert nonEmpty(@lFullTree), "tree is empty"
|
229
|
+
if isSetName(@lFullTree[0])
|
230
|
+
LOGTAML 'lFullTree', @lFullTree
|
231
|
+
croak "tree cannot begin with a set name"
|
232
|
+
debug "return from checkTree()"
|
233
|
+
return
|
234
|
+
|
235
|
+
# ..........................................................
|
236
|
+
|
237
|
+
checkReplacers: (h) ->
|
238
|
+
|
239
|
+
assert isHash(h), "replacers is not a hash"
|
240
|
+
for key,func of h
|
241
|
+
assert isSetName(key) || isSectionName(key), "bad replacer key"
|
242
|
+
assert isFunction(func),
|
243
|
+
"replacer for #{OL(key)} is not a function"
|
244
|
+
return
|
245
|
+
|
package/src/SectionMap.js
CHANGED
@@ -4,22 +4,20 @@ var isSectionName, isSetName;
|
|
4
4
|
|
5
5
|
import {
|
6
6
|
assert,
|
7
|
-
croak
|
7
|
+
croak,
|
8
|
+
LOG,
|
9
|
+
LOGVALUE,
|
10
|
+
LOGTAML,
|
11
|
+
debug,
|
12
|
+
isTAML,
|
13
|
+
fromTAML
|
8
14
|
} from '@jdeighan/exceptions';
|
9
15
|
|
10
|
-
import {
|
11
|
-
LOG
|
12
|
-
} from '@jdeighan/exceptions/log';
|
13
|
-
|
14
|
-
import {
|
15
|
-
debug
|
16
|
-
} from '@jdeighan/exceptions/debug';
|
17
|
-
|
18
16
|
import {
|
19
17
|
pass,
|
20
18
|
undef,
|
21
|
-
|
22
|
-
|
19
|
+
def,
|
20
|
+
notdef,
|
23
21
|
OL,
|
24
22
|
isEmpty,
|
25
23
|
nonEmpty,
|
@@ -28,18 +26,16 @@ import {
|
|
28
26
|
isArray,
|
29
27
|
isUniqueTree,
|
30
28
|
isNonEmptyString,
|
31
|
-
isNonEmptyArray
|
29
|
+
isNonEmptyArray,
|
30
|
+
isFunction,
|
31
|
+
jsType,
|
32
|
+
isArrayOfStrings
|
32
33
|
} from '@jdeighan/coffee-utils';
|
33
34
|
|
34
35
|
import {
|
35
36
|
toBlock
|
36
37
|
} from '@jdeighan/coffee-utils/block';
|
37
38
|
|
38
|
-
import {
|
39
|
-
isTAML,
|
40
|
-
fromTAML
|
41
|
-
} from '@jdeighan/coffee-utils/taml';
|
42
|
-
|
43
39
|
import {
|
44
40
|
Section
|
45
41
|
} from '@jdeighan/coffee-utils/section';
|
@@ -56,142 +52,170 @@ isSetName = function(name) {
|
|
56
52
|
|
57
53
|
// ---------------------------------------------------------------------------
|
58
54
|
export var SectionMap = class SectionMap {
|
59
|
-
constructor(
|
60
|
-
this.
|
61
|
-
// ---
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
//
|
68
|
-
this.
|
69
|
-
|
70
|
-
this.
|
71
|
-
this.
|
72
|
-
|
55
|
+
constructor(tree, hReplacers = {}) {
|
56
|
+
this.hReplacers = hReplacers;
|
57
|
+
// --- tree is a tree of section/set names
|
58
|
+
// or a TAML string that converts to one
|
59
|
+
// --- hReplacers are callbacks that are called
|
60
|
+
// when a set or section is processed
|
61
|
+
// should be <name> -> <function>
|
62
|
+
// <name> can be a section name or a set name
|
63
|
+
// <function> should be <block> -> <block>
|
64
|
+
debug("enter SectionMap()", tree, this.hReplacers);
|
65
|
+
this.checkTree(tree);
|
66
|
+
this.checkReplacers(this.hReplacers);
|
67
|
+
this.hSections = {}; // --- {section name: Section Object}
|
68
|
+
this.hSets = {
|
69
|
+
ALL: this.lFullTree // --- {set name: array of parts}
|
70
|
+
};
|
71
|
+
this.init(this.lFullTree);
|
72
|
+
debug('hSections', this.hSections);
|
73
|
+
debug('hSets', this.hSets);
|
74
|
+
debug("return from SectionMap()");
|
73
75
|
}
|
74
76
|
|
75
77
|
// ..........................................................
|
76
|
-
|
77
|
-
var firstItem, i, item,
|
78
|
-
debug("enter
|
78
|
+
init(lTree) {
|
79
|
+
var firstItem, i, item, len;
|
80
|
+
debug("enter init()", lTree);
|
79
81
|
assert(isArray(lTree), "not an array");
|
80
82
|
assert(nonEmpty(lTree), "empty array");
|
81
83
|
firstItem = lTree[0];
|
82
84
|
if (isSetName(firstItem)) {
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
}
|
96
|
-
|
97
|
-
for (j = 0, len1 = lTree.length; j < len1; j++) {
|
98
|
-
item = lTree[j];
|
99
|
-
if (isArray(item)) {
|
100
|
-
this.build(item);
|
101
|
-
} else if (isSectionName(item)) {
|
102
|
-
this.hSections[item] = new Section(item);
|
103
|
-
} else {
|
104
|
-
croak(`Bad section tree: ${OL(this.lSectionTree)}`);
|
105
|
-
}
|
85
|
+
debug(`found set name ${OL(firstItem)}`);
|
86
|
+
lTree = lTree.slice(1);
|
87
|
+
this.mkSet(firstItem, lTree);
|
88
|
+
}
|
89
|
+
for (i = 0, len = lTree.length; i < len; i++) {
|
90
|
+
item = lTree[i];
|
91
|
+
if (isArray(item)) {
|
92
|
+
debug("init subtree");
|
93
|
+
this.init(item);
|
94
|
+
} else if (isSectionName(item)) {
|
95
|
+
debug(`mkSection ${OL(item)}`);
|
96
|
+
this.mkSection(item);
|
97
|
+
} else {
|
98
|
+
assert(isString(item), `Bad item in tree: ${OL(item)}`);
|
106
99
|
}
|
107
100
|
}
|
108
|
-
debug("return from
|
101
|
+
debug("return from init()");
|
102
|
+
}
|
103
|
+
|
104
|
+
// ..........................................................
|
105
|
+
mkSet(name, lTree) {
|
106
|
+
assert(isArray(lTree), "tree is not an array");
|
107
|
+
assert(nonEmpty(lTree), "set without sections");
|
108
|
+
assert(notdef(this.hSets[name]), `set ${OL(name)} already exists`);
|
109
|
+
this.hSets[name] = lTree;
|
109
110
|
}
|
110
111
|
|
111
112
|
// ..........................................................
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
//
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
//
|
124
|
-
//
|
125
|
-
//
|
126
|
-
if (
|
127
|
-
debug(
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
debug("desc is entire tree");
|
133
|
-
desc = this.lSectionTree;
|
113
|
+
mkSection(name) {
|
114
|
+
assert(notdef(this.hSections[name]), "duplicate section name");
|
115
|
+
this.hSections[name] = new Section(name, this.hReplacers[name]);
|
116
|
+
}
|
117
|
+
|
118
|
+
// ..........................................................
|
119
|
+
getBlock(desc = 'ALL') {
|
120
|
+
var block, item, lBlocks, replacer;
|
121
|
+
// ..........................................................
|
122
|
+
// --- desc can be:
|
123
|
+
// a section name
|
124
|
+
// a set name
|
125
|
+
// an array of section or set names or literal strings
|
126
|
+
// i.e. it should NOT contain sub-arrays
|
127
|
+
if (isString(desc)) {
|
128
|
+
debug(`enter SectionMap.getBlock(${OL(desc)})`);
|
129
|
+
} else if (isArrayOfStrings(desc)) {
|
130
|
+
debug("enter SectionMap.getBlock()", desc);
|
131
|
+
} else {
|
132
|
+
croak(`Bad desc: ${OL(desc)}`);
|
134
133
|
}
|
135
|
-
if (
|
136
|
-
debug("item is
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
if (
|
148
|
-
|
149
|
-
|
134
|
+
if (isSectionName(desc)) {
|
135
|
+
debug("item is a section name");
|
136
|
+
// --- a section's getBlock() applies any replacer
|
137
|
+
block = this.section(desc).getBlock();
|
138
|
+
} else if (isSetName(desc)) {
|
139
|
+
debug("item is a set name");
|
140
|
+
lBlocks = (function() {
|
141
|
+
var i, len, ref, results;
|
142
|
+
ref = this.hSets[desc];
|
143
|
+
results = [];
|
144
|
+
for (i = 0, len = ref.length; i < len; i++) {
|
145
|
+
item = ref[i];
|
146
|
+
if (isArray(item)) {
|
147
|
+
results.push(this.getBlock(item[0]));
|
148
|
+
} else if (isString(item)) {
|
149
|
+
results.push(this.getBlock(item));
|
150
150
|
} else {
|
151
|
-
|
151
|
+
results.push(croak(`Item in set ${desc} is not a string or array`));
|
152
152
|
}
|
153
|
-
} else if (isString(item) && nonEmpty(item)) {
|
154
|
-
debug("add string", item);
|
155
|
-
lBlocks.push(item);
|
156
|
-
} else {
|
157
|
-
croak(`Bad item: ${OL(item)}`);
|
158
153
|
}
|
159
|
-
|
154
|
+
return results;
|
155
|
+
}).call(this);
|
160
156
|
block = toBlock(lBlocks);
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
debug(`REPLACE ${setName} with`, block);
|
166
|
-
} else {
|
167
|
-
debug(`NO REPLACER for ${setName}`);
|
168
|
-
}
|
169
|
-
}
|
170
|
-
} else if (isSectionName(desc)) {
|
171
|
-
debug("item is a section name");
|
172
|
-
block = this.section(desc).getBlock();
|
173
|
-
if (defined(proc = hReplacers[desc])) {
|
174
|
-
debug(`REPLACE ${desc}`);
|
175
|
-
block = proc(block);
|
176
|
-
} else {
|
177
|
-
debug(`NO REPLACER for ${desc}`);
|
157
|
+
replacer = this.hReplacers[desc];
|
158
|
+
debug(`replacer for is ${OL(replacer)}`);
|
159
|
+
if (def(replacer)) {
|
160
|
+
block = replacer(block);
|
178
161
|
}
|
179
|
-
} else if (
|
180
|
-
debug("item is a
|
181
|
-
|
162
|
+
} else if (isString(desc)) {
|
163
|
+
debug("item is a literal string");
|
164
|
+
// --- a literal string
|
165
|
+
block = desc;
|
166
|
+
} else if (isArray(desc)) {
|
167
|
+
debug("item is an array");
|
168
|
+
lBlocks = (function() {
|
169
|
+
var i, len, results;
|
170
|
+
results = [];
|
171
|
+
for (i = 0, len = desc.length; i < len; i++) {
|
172
|
+
item = desc[i];
|
173
|
+
results.push(this.getBlock(item));
|
174
|
+
}
|
175
|
+
return results;
|
176
|
+
}).call(this);
|
177
|
+
block = toBlock(lBlocks);
|
182
178
|
} else {
|
183
|
-
croak(`Bad
|
179
|
+
croak(`Bad arg: ${OL(desc)}`);
|
184
180
|
}
|
185
181
|
debug("return from SectionMap.getBlock()", block);
|
186
182
|
return block;
|
187
183
|
}
|
188
184
|
|
189
185
|
// ..........................................................
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
186
|
+
// --- does NOT call any replacers, and skips literal strings
|
187
|
+
// so only useful for isEmpty() and nonEmpty()
|
188
|
+
* allSections(desc = undef) {
|
189
|
+
var i, item, j, len, len1, name, ref;
|
190
|
+
debug("enter allSections()", desc);
|
191
|
+
if (notdef(desc)) {
|
192
|
+
desc = this.lFullTree;
|
193
|
+
}
|
194
|
+
if (isSectionName(desc)) {
|
195
|
+
debug("is section name");
|
196
|
+
yield this.section(desc);
|
197
|
+
} else if (isSetName(desc)) {
|
198
|
+
debug("is set name");
|
199
|
+
ref = this.hSets[desc];
|
200
|
+
for (i = 0, len = ref.length; i < len; i++) {
|
201
|
+
name = ref[i];
|
202
|
+
yield* this.allSections(name);
|
203
|
+
}
|
204
|
+
} else if (isArray(desc)) {
|
205
|
+
debug("is array");
|
206
|
+
for (j = 0, len1 = desc.length; j < len1; j++) {
|
207
|
+
item = desc[j];
|
208
|
+
yield* this.allSections(item);
|
209
|
+
}
|
210
|
+
}
|
211
|
+
debug("return from allSections()");
|
212
|
+
}
|
213
|
+
|
214
|
+
// ..........................................................
|
215
|
+
isEmpty(desc = undef) {
|
216
|
+
var ref, sect;
|
217
|
+
ref = this.allSections(desc);
|
218
|
+
for (sect of ref) {
|
195
219
|
if (sect.nonEmpty()) {
|
196
220
|
return false;
|
197
221
|
}
|
@@ -200,11 +224,10 @@ export var SectionMap = class SectionMap {
|
|
200
224
|
}
|
201
225
|
|
202
226
|
// ..........................................................
|
203
|
-
nonEmpty() {
|
204
|
-
var
|
205
|
-
ref = this.
|
206
|
-
for (
|
207
|
-
sect = ref[name];
|
227
|
+
nonEmpty(desc = undef) {
|
228
|
+
var ref, sect;
|
229
|
+
ref = this.allSections(desc);
|
230
|
+
for (sect of ref) {
|
208
231
|
if (sect.nonEmpty()) {
|
209
232
|
return true;
|
210
233
|
}
|
@@ -216,7 +239,7 @@ export var SectionMap = class SectionMap {
|
|
216
239
|
section(name) {
|
217
240
|
var sect;
|
218
241
|
sect = this.hSections[name];
|
219
|
-
assert(
|
242
|
+
assert(def(sect), `No section named ${OL(name)}`);
|
220
243
|
return sect;
|
221
244
|
}
|
222
245
|
|
@@ -225,8 +248,8 @@ export var SectionMap = class SectionMap {
|
|
225
248
|
var lSubTree;
|
226
249
|
assert(isSetName(name), `bad set name ${OL(name)}`);
|
227
250
|
lSubTree = this.hSets[name];
|
228
|
-
assert(
|
229
|
-
return this.section(lSubTree[
|
251
|
+
assert(def(lSubTree), `no such set ${OL(name)}`);
|
252
|
+
return this.section(lSubTree[0]);
|
230
253
|
}
|
231
254
|
|
232
255
|
// ..........................................................
|
@@ -234,8 +257,38 @@ export var SectionMap = class SectionMap {
|
|
234
257
|
var lSubTree;
|
235
258
|
assert(isSetName(name), `bad set name ${OL(name)}`);
|
236
259
|
lSubTree = this.hSets[name];
|
237
|
-
assert(
|
260
|
+
assert(def(lSubTree), `no such set ${OL(name)}`);
|
238
261
|
return this.section(lSubTree[lSubTree.length - 1]);
|
239
262
|
}
|
240
263
|
|
264
|
+
// ..........................................................
|
265
|
+
checkTree(tree) {
|
266
|
+
debug("enter checkTree()");
|
267
|
+
if (isString(tree)) {
|
268
|
+
debug("tree is a string");
|
269
|
+
assert(isTAML(tree), "not TAML");
|
270
|
+
this.lFullTree = fromTAML(tree);
|
271
|
+
} else {
|
272
|
+
this.lFullTree = tree;
|
273
|
+
}
|
274
|
+
assert(isArray(this.lFullTree), "not an array");
|
275
|
+
assert(nonEmpty(this.lFullTree), "tree is empty");
|
276
|
+
if (isSetName(this.lFullTree[0])) {
|
277
|
+
LOGTAML('lFullTree', this.lFullTree);
|
278
|
+
croak("tree cannot begin with a set name");
|
279
|
+
}
|
280
|
+
debug("return from checkTree()");
|
281
|
+
}
|
282
|
+
|
283
|
+
// ..........................................................
|
284
|
+
checkReplacers(h) {
|
285
|
+
var func, key;
|
286
|
+
assert(isHash(h), "replacers is not a hash");
|
287
|
+
for (key in h) {
|
288
|
+
func = h[key];
|
289
|
+
assert(isSetName(key) || isSectionName(key), "bad replacer key");
|
290
|
+
assert(isFunction(func), `replacer for ${OL(key)} is not a function`);
|
291
|
+
}
|
292
|
+
}
|
293
|
+
|
241
294
|
};
|
package/src/block.coffee
CHANGED
@@ -63,7 +63,8 @@ export toBlock = (lLines) ->
|
|
63
63
|
|
64
64
|
if notdefined(lLines)
|
65
65
|
return undef
|
66
|
-
assert isArrayOfStrings(lLines),
|
66
|
+
assert isArrayOfStrings(lLines),
|
67
|
+
"lLines is not an array of strings: #{OL(lLines)}"
|
67
68
|
lNewLines = []
|
68
69
|
for line in lLines
|
69
70
|
if defined(line)
|
package/src/block.js
CHANGED
@@ -90,7 +90,7 @@ export var toBlock = function(lLines) {
|
|
90
90
|
if (notdefined(lLines)) {
|
91
91
|
return undef;
|
92
92
|
}
|
93
|
-
assert(isArrayOfStrings(lLines), `lLines is not an array: ${OL(lLines)}`);
|
93
|
+
assert(isArrayOfStrings(lLines), `lLines is not an array of strings: ${OL(lLines)}`);
|
94
94
|
lNewLines = [];
|
95
95
|
for (i = 0, len = lLines.length; i < len; i++) {
|
96
96
|
line = lLines[i];
|
package/src/fs.coffee
CHANGED
@@ -5,7 +5,7 @@ import urllib from 'url'
|
|
5
5
|
import fs from 'fs'
|
6
6
|
import NReadLines from 'n-readlines'
|
7
7
|
|
8
|
-
import {assert, croak, LOG, fromTAML} from '@jdeighan/exceptions'
|
8
|
+
import {assert, croak, debug, LOG, fromTAML} from '@jdeighan/exceptions'
|
9
9
|
import {
|
10
10
|
undef, pass, defined, rtrim, isEmpty, nonEmpty, getOptions,
|
11
11
|
isString, isArray, isHash, isRegExp, isFunction, OL,
|
@@ -377,6 +377,7 @@ export parseSource = (source) ->
|
|
377
377
|
# }
|
378
378
|
# --- NOTE: source may be a file URL, e.g. import.meta.url
|
379
379
|
|
380
|
+
debug "enter parseSource(#{OL(source)})"
|
380
381
|
assert isString(source),\
|
381
382
|
"parseSource(): source not a string: #{OL(source)}"
|
382
383
|
if source == 'unit test'
|
@@ -413,6 +414,7 @@ export parseSource = (source) ->
|
|
413
414
|
([A-Za-z_]+)
|
414
415
|
$///)
|
415
416
|
hSourceInfo.purpose = lMatches[1]
|
417
|
+
debug "return from parseSource()", hSourceInfo
|
416
418
|
return hSourceInfo
|
417
419
|
|
418
420
|
# ---------------------------------------------------------------------------
|
package/src/fs.js
CHANGED
@@ -13,6 +13,7 @@ import NReadLines from 'n-readlines';
|
|
13
13
|
import {
|
14
14
|
assert,
|
15
15
|
croak,
|
16
|
+
debug,
|
16
17
|
LOG,
|
17
18
|
fromTAML
|
18
19
|
} from '@jdeighan/exceptions';
|
@@ -446,6 +447,7 @@ export var parseSource = function(source) {
|
|
446
447
|
// purpose
|
447
448
|
// }
|
448
449
|
// --- NOTE: source may be a file URL, e.g. import.meta.url
|
450
|
+
debug(`enter parseSource(${OL(source)})`);
|
449
451
|
assert(isString(source), `parseSource(): source not a string: ${OL(source)}`);
|
450
452
|
if (source === 'unit test') {
|
451
453
|
croak("A source of 'unit test' is deprecated");
|
@@ -481,6 +483,7 @@ export var parseSource = function(source) {
|
|
481
483
|
hSourceInfo.purpose = lMatches[1];
|
482
484
|
}
|
483
485
|
}
|
486
|
+
debug("return from parseSource()", hSourceInfo);
|
484
487
|
return hSourceInfo;
|
485
488
|
};
|
486
489
|
|
package/src/utils.coffee
CHANGED
@@ -11,8 +11,11 @@ import {
|
|
11
11
|
isEmpty, nonEmpty, chomp, rtrim, setCharsAt, words, getOptions,
|
12
12
|
} from '@jdeighan/exceptions/utils'
|
13
13
|
|
14
|
+
def = defined
|
15
|
+
notdef = notdefined
|
16
|
+
|
14
17
|
export {
|
15
|
-
undef, pass, defined, notdefined, LOG, sep_dash, sep_eq,
|
18
|
+
undef, pass, def, defined, notdef, notdefined, LOG, sep_dash, sep_eq,
|
16
19
|
deepCopy, escapeStr, unescapeStr, hasChar, quoted, OL,
|
17
20
|
isString, isNumber, isInteger, isHash, isArray, isBoolean,
|
18
21
|
isConstructor, isFunction, isRegExp, isObject, getClassName,
|
@@ -137,22 +140,24 @@ export pushCond = (lItems, item, doPush=notInArray) ->
|
|
137
140
|
# ---------------------------------------------------------------------------
|
138
141
|
|
139
142
|
export isArrayOfHashes = (lItems) ->
|
143
|
+
# --- undefined items are allowed
|
140
144
|
|
141
145
|
if ! isArray(lItems)
|
142
146
|
return false
|
143
147
|
for item in lItems
|
144
|
-
if ! isHash(item)
|
148
|
+
if defined(item) && ! isHash(item)
|
145
149
|
return false
|
146
150
|
return true
|
147
151
|
|
148
152
|
# ---------------------------------------------------------------------------
|
149
153
|
|
150
154
|
export isArrayOfStrings = (lItems) ->
|
155
|
+
# --- undefined items are allowed
|
151
156
|
|
152
157
|
if ! isArray(lItems)
|
153
158
|
return false
|
154
159
|
for item in lItems
|
155
|
-
if ! isString(item)
|
160
|
+
if defined(item) && ! isString(item)
|
156
161
|
return false
|
157
162
|
return true
|
158
163
|
|
package/src/utils.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
// Generated by CoffeeScript 2.7.0
|
2
|
-
// utils.coffee
|
3
|
-
var
|
2
|
+
// utils.coffee
|
3
|
+
var def, notdef,
|
4
|
+
hasProp = {}.hasOwnProperty;
|
4
5
|
|
5
6
|
import {
|
6
7
|
assert,
|
@@ -45,10 +46,16 @@ import {
|
|
45
46
|
getOptions
|
46
47
|
} from '@jdeighan/exceptions/utils';
|
47
48
|
|
49
|
+
def = defined;
|
50
|
+
|
51
|
+
notdef = notdefined;
|
52
|
+
|
48
53
|
export {
|
49
54
|
undef,
|
50
55
|
pass,
|
56
|
+
def,
|
51
57
|
defined,
|
58
|
+
notdef,
|
52
59
|
notdefined,
|
53
60
|
LOG,
|
54
61
|
sep_dash,
|
@@ -202,7 +209,7 @@ export var isArrayOfHashes = function(lItems) {
|
|
202
209
|
}
|
203
210
|
for (i = 0, len = lItems.length; i < len; i++) {
|
204
211
|
item = lItems[i];
|
205
|
-
if (!isHash(item)) {
|
212
|
+
if (defined(item) && !isHash(item)) {
|
206
213
|
return false;
|
207
214
|
}
|
208
215
|
}
|
@@ -217,7 +224,7 @@ export var isArrayOfStrings = function(lItems) {
|
|
217
224
|
}
|
218
225
|
for (i = 0, len = lItems.length; i < len; i++) {
|
219
226
|
item = lItems[i];
|
220
|
-
if (!isString(item)) {
|
227
|
+
if (defined(item) && !isString(item)) {
|
221
228
|
return false;
|
222
229
|
}
|
223
230
|
}
|
package/src/placeholders.coffee
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# placeholders.coffee
|
2
|
-
|
3
|
-
import {assert, croak} from '@jdeighan/exceptions'
|
4
|
-
import {undef, defined} from '@jdeighan/coffee-utils'
|
5
|
-
|
6
|
-
hDefOptions = {
|
7
|
-
pre: '__'
|
8
|
-
post: '__'
|
9
|
-
}
|
10
|
-
|
11
|
-
# ---------------------------------------------------------------------------
|
12
|
-
|
13
|
-
export phStr = (name, hOptions=hDefOptions) ->
|
14
|
-
|
15
|
-
{pre, post} = hOptions
|
16
|
-
return "#{pre}#{name}#{post}"
|
17
|
-
|
18
|
-
# ---------------------------------------------------------------------------
|
19
|
-
|
20
|
-
export phReplace = (str, hValues, hOptions=hDefOptions) ->
|
21
|
-
|
22
|
-
{pre, post} = hOptions
|
23
|
-
return str.replace(
|
24
|
-
/// #{pre} ([A-Za-z_][A-Za-z0-9_]*) #{post} ///g,
|
25
|
-
(_, name) -> hValues[name]
|
26
|
-
)
|
package/src/placeholders.js
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
// Generated by CoffeeScript 2.7.0
|
2
|
-
// placeholders.coffee
|
3
|
-
var hDefOptions;
|
4
|
-
|
5
|
-
import {
|
6
|
-
assert,
|
7
|
-
croak
|
8
|
-
} from '@jdeighan/exceptions';
|
9
|
-
|
10
|
-
import {
|
11
|
-
undef,
|
12
|
-
defined
|
13
|
-
} from '@jdeighan/coffee-utils';
|
14
|
-
|
15
|
-
hDefOptions = {
|
16
|
-
pre: '__',
|
17
|
-
post: '__'
|
18
|
-
};
|
19
|
-
|
20
|
-
// ---------------------------------------------------------------------------
|
21
|
-
export var phStr = function(name, hOptions = hDefOptions) {
|
22
|
-
var post, pre;
|
23
|
-
({pre, post} = hOptions);
|
24
|
-
return `${pre}${name}${post}`;
|
25
|
-
};
|
26
|
-
|
27
|
-
// ---------------------------------------------------------------------------
|
28
|
-
export var phReplace = function(str, hValues, hOptions = hDefOptions) {
|
29
|
-
var post, pre;
|
30
|
-
({pre, post} = hOptions);
|
31
|
-
return str.replace(RegExp(`${pre}([A-Za-z_][A-Za-z0-9_]*)${post}`, "g"), function(_, name) {
|
32
|
-
return hValues[name];
|
33
|
-
});
|
34
|
-
};
|