jostraca 0.4.0 → 0.6.0
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/dist/cmp/Content.d.ts +2 -0
- package/dist/cmp/Content.js +12 -0
- package/dist/cmp/Content.js.map +1 -0
- package/dist/cmp/Copy.d.ts +2 -0
- package/dist/cmp/Copy.js +13 -0
- package/dist/cmp/Copy.js.map +1 -0
- package/dist/cmp/File.d.ts +2 -0
- package/dist/cmp/File.js +13 -0
- package/dist/cmp/File.js.map +1 -0
- package/dist/cmp/Folder.d.ts +2 -0
- package/dist/cmp/Folder.js +12 -0
- package/dist/cmp/Folder.js.map +1 -0
- package/dist/cmp/Project.d.ts +2 -0
- package/dist/cmp/Project.js +13 -0
- package/dist/cmp/Project.js.map +1 -0
- package/dist/jostraca.d.ts +10 -34
- package/dist/jostraca.js +103 -294
- package/dist/jostraca.js.map +1 -1
- package/dist/op/ContentOp.d.ts +6 -0
- package/dist/op/ContentOp.js +12 -0
- package/dist/op/ContentOp.js.map +1 -0
- package/dist/op/CopyOp.d.ts +6 -0
- package/dist/op/CopyOp.js +188 -0
- package/dist/op/CopyOp.js.map +1 -0
- package/dist/op/FileOp.d.ts +6 -0
- package/dist/op/FileOp.js +43 -0
- package/dist/op/FileOp.js.map +1 -0
- package/dist/op/FolderOp.d.ts +6 -0
- package/dist/op/FolderOp.js +23 -0
- package/dist/op/FolderOp.js.map +1 -0
- package/dist/op/NoneOp.d.ts +6 -0
- package/dist/op/NoneOp.js +9 -0
- package/dist/op/NoneOp.js.map +1 -0
- package/dist/op/ProjectOp.d.ts +6 -0
- package/dist/op/ProjectOp.js +24 -0
- package/dist/op/ProjectOp.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/utility.d.ts +44 -0
- package/dist/utility.js +213 -0
- package/dist/utility.js.map +1 -0
- package/package.json +4 -4
- package/src/cmp/Content.ts +19 -0
- package/src/cmp/Copy.ts +21 -0
- package/src/cmp/File.ts +21 -0
- package/src/cmp/Folder.ts +21 -0
- package/src/cmp/Project.ts +22 -0
- package/src/jostraca.ts +118 -380
- package/src/op/ContentOp.ts +18 -0
- package/src/op/CopyOp.ts +229 -0
- package/src/op/FileOp.ts +58 -0
- package/src/op/FolderOp.ts +31 -0
- package/src/op/NoneOp.ts +14 -0
- package/src/op/ProjectOp.ts +33 -0
- package/src/utility.ts +306 -0
package/src/jostraca.ts
CHANGED
|
@@ -1,32 +1,46 @@
|
|
|
1
1
|
/* Copyright (c) 2024 Richard Rodger, MIT License */
|
|
2
2
|
|
|
3
3
|
import * as Fs from 'node:fs'
|
|
4
|
+
import Path from 'node:path'
|
|
4
5
|
|
|
5
6
|
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
import type {
|
|
10
|
+
JostracaOptions,
|
|
11
|
+
Node,
|
|
12
|
+
OpDef,
|
|
13
|
+
Component,
|
|
14
|
+
} from './utility'
|
|
11
15
|
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
import {
|
|
18
|
+
each,
|
|
19
|
+
select,
|
|
20
|
+
get,
|
|
21
|
+
getx,
|
|
22
|
+
camelify,
|
|
23
|
+
snakify,
|
|
24
|
+
kebabify,
|
|
25
|
+
cmap,
|
|
26
|
+
vmap,
|
|
27
|
+
names,
|
|
28
|
+
} from './utility'
|
|
18
29
|
|
|
19
30
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
content?: any[]
|
|
26
|
-
}
|
|
31
|
+
import { Content } from './cmp/Content'
|
|
32
|
+
import { Copy } from './cmp/Copy'
|
|
33
|
+
import { File } from './cmp/File'
|
|
34
|
+
import { Folder } from './cmp/Folder'
|
|
35
|
+
import { Project } from './cmp/Project'
|
|
27
36
|
|
|
37
|
+
import { CopyOp } from './op/CopyOp'
|
|
38
|
+
import { ProjectOp } from './op/ProjectOp'
|
|
39
|
+
import { FolderOp } from './op/FolderOp'
|
|
40
|
+
import { FileOp } from './op/FileOp'
|
|
41
|
+
import { ContentOp } from './op/ContentOp'
|
|
42
|
+
import { NoneOp } from './op/NoneOp'
|
|
28
43
|
|
|
29
|
-
type Component = (props: any, children?: any) => void
|
|
30
44
|
|
|
31
45
|
|
|
32
46
|
const GLOBAL = (global as any)
|
|
@@ -37,35 +51,40 @@ function Jostraca() {
|
|
|
37
51
|
GLOBAL.jostraca = new AsyncLocalStorage()
|
|
38
52
|
|
|
39
53
|
|
|
40
|
-
function generate(opts: JostracaOptions, root: Function) {
|
|
54
|
+
async function generate(opts: JostracaOptions, root: Function) {
|
|
41
55
|
const fs = opts.fs || Fs
|
|
42
56
|
const meta = opts.meta || {}
|
|
43
57
|
const folder = opts.folder || '.'
|
|
44
58
|
|
|
45
59
|
const ctx$ = {
|
|
46
|
-
fs,
|
|
47
60
|
folder,
|
|
48
61
|
content: null,
|
|
49
62
|
meta,
|
|
63
|
+
fs,
|
|
50
64
|
}
|
|
51
65
|
|
|
52
|
-
GLOBAL.jostraca.run(ctx$, () => {
|
|
66
|
+
return GLOBAL.jostraca.run(ctx$, async () => {
|
|
53
67
|
try {
|
|
68
|
+
// Define phase
|
|
54
69
|
root()
|
|
55
70
|
|
|
56
71
|
const ctx$ = GLOBAL.jostraca.getStore()
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
|
|
73
|
+
// console.dir(ctx$.node, { depth: null })
|
|
74
|
+
|
|
75
|
+
// Build phase
|
|
76
|
+
|
|
77
|
+
const buildctx = {
|
|
78
|
+
fs,
|
|
79
|
+
folder,
|
|
80
|
+
current: {
|
|
81
|
+
folder: {
|
|
82
|
+
parent: folder
|
|
67
83
|
}
|
|
68
|
-
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
await build(ctx$, buildctx)
|
|
87
|
+
return buildctx
|
|
69
88
|
}
|
|
70
89
|
catch (err: any) {
|
|
71
90
|
console.log('JOSTRACA ERROR:', err)
|
|
@@ -75,98 +94,80 @@ function Jostraca() {
|
|
|
75
94
|
}
|
|
76
95
|
|
|
77
96
|
|
|
78
|
-
function build(
|
|
79
|
-
|
|
80
|
-
}
|
|
97
|
+
async function build(ctx$: any, buildctx: any) {
|
|
98
|
+
const topnode = ctx$.node
|
|
81
99
|
|
|
100
|
+
let info = { exclude: [], last: -1 }
|
|
101
|
+
const infopath = Path.join(buildctx.folder, '.jostraca', 'info.json')
|
|
82
102
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
throw new Error('missing op: ' + node.kind)
|
|
103
|
+
try {
|
|
104
|
+
info = JSON.parse(ctx$.fs.readFileSync(
|
|
105
|
+
infopath, 'utf8'))
|
|
87
106
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (node.children) {
|
|
92
|
-
for (let childnode of node.children) {
|
|
93
|
-
step(childnode, ctx)
|
|
94
|
-
}
|
|
107
|
+
catch (err: any) {
|
|
108
|
+
// console.log(err)
|
|
109
|
+
// TODO: file not foound ignored, handle others!
|
|
95
110
|
}
|
|
96
111
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const opmap: any = {
|
|
103
|
-
|
|
104
|
-
project: {
|
|
105
|
-
before(node: Node, ctx: any) {
|
|
106
|
-
const cproject: any = ctx.current.project = (ctx.current.project || {})
|
|
107
|
-
cproject.node = node
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
after(_node: Node, _ctx: any) {
|
|
111
|
-
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
|
|
112
|
+
buildctx.info = info
|
|
113
|
+
// console.log('B-INFO', buildctx.info)
|
|
115
114
|
|
|
116
|
-
|
|
117
|
-
before(node: Node, ctx: any) {
|
|
118
|
-
const cfolder = ctx.current.folder = (ctx.current.folder || {})
|
|
115
|
+
await step(topnode, ctx$, buildctx)
|
|
119
116
|
|
|
120
|
-
cfolder.node = node
|
|
121
|
-
cfolder.path = (cfolder.path || [ctx.current.folder.parent])
|
|
122
|
-
cfolder.path.push(node.name)
|
|
123
|
-
|
|
124
|
-
let fullpath = cfolder.path.join('/')
|
|
125
|
-
ctx.fs.mkdirSync(fullpath, { recursive: true })
|
|
126
|
-
},
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
after(_node: Node, ctx: any) {
|
|
130
|
-
const cfolder = ctx.current.folder
|
|
131
|
-
cfolder.path.length = cfolder.path.length - 1
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
117
|
|
|
118
|
+
try {
|
|
119
|
+
const info = {
|
|
120
|
+
last: Date.now(),
|
|
121
|
+
exclude: buildctx.info.exclude,
|
|
122
|
+
}
|
|
123
|
+
ctx$.fs.mkdirSync(Path.dirname(infopath), { recursive: true })
|
|
124
|
+
ctx$.fs.writeFileSync(infopath, JSON.stringify(info, null, 2))
|
|
125
|
+
}
|
|
126
|
+
catch (err: any) {
|
|
127
|
+
console.log(err)
|
|
128
|
+
// TODO: file not foound ignored, handle others!
|
|
129
|
+
}
|
|
135
130
|
|
|
136
|
-
file: {
|
|
137
|
-
before(node: Node, ctx: any) {
|
|
138
|
-
const cfile = ctx.current.file = node
|
|
139
|
-
cfile.path = ctx.current.folder.path.join('/') + '/' + node.name
|
|
140
|
-
cfile.content = []
|
|
141
|
-
},
|
|
142
131
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const content = cfile.content.join('')
|
|
146
|
-
ctx.fs.writeFileSync(cfile.path, content)
|
|
147
|
-
},
|
|
148
|
-
},
|
|
132
|
+
return { node: topnode, ctx$, buildctx }
|
|
133
|
+
}
|
|
149
134
|
|
|
150
135
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
136
|
+
async function step(node: Node, ctx$: any, buildctx: any) {
|
|
137
|
+
try {
|
|
138
|
+
const op = opmap[node.kind]
|
|
139
|
+
if (null == op) {
|
|
140
|
+
throw new Error('missing op: ' + node.kind)
|
|
141
|
+
}
|
|
156
142
|
|
|
157
|
-
|
|
158
|
-
},
|
|
159
|
-
},
|
|
143
|
+
await op.before(node, ctx$, buildctx)
|
|
160
144
|
|
|
145
|
+
if (node.children) {
|
|
146
|
+
for (let childnode of node.children) {
|
|
147
|
+
await step(childnode, ctx$, buildctx)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
161
150
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
151
|
+
await op.after(node, ctx$, buildctx)
|
|
152
|
+
}
|
|
153
|
+
catch (err: any) {
|
|
154
|
+
if (err.jostraca) {
|
|
155
|
+
throw err
|
|
156
|
+
}
|
|
157
|
+
err.jostraca = true
|
|
158
|
+
err.step = node.kind
|
|
159
|
+
throw err
|
|
160
|
+
}
|
|
161
|
+
}
|
|
165
162
|
|
|
166
|
-
after(_node: Node, _ctx: any) {
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
163
|
|
|
164
|
+
const opmap: Record<string, OpDef> = {
|
|
165
|
+
project: ProjectOp,
|
|
166
|
+
folder: FolderOp,
|
|
167
|
+
file: FileOp,
|
|
168
|
+
content: ContentOp,
|
|
169
|
+
copy: CopyOp,
|
|
170
|
+
none: NoneOp,
|
|
170
171
|
}
|
|
171
172
|
|
|
172
173
|
|
|
@@ -176,51 +177,6 @@ function Jostraca() {
|
|
|
176
177
|
}
|
|
177
178
|
|
|
178
179
|
|
|
179
|
-
const Code = cmp(function Code(props: any) {
|
|
180
|
-
props.ctx$.node.kind = 'content'
|
|
181
|
-
let src = props.arg
|
|
182
|
-
props.ctx$.node.content = src
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const File = cmp(function File(props: any, children: any) {
|
|
187
|
-
props.ctx$.node.kind = 'file'
|
|
188
|
-
props.ctx$.node.name = props.name
|
|
189
|
-
|
|
190
|
-
// Code('// FILE START: ' + props.name + '\n')
|
|
191
|
-
|
|
192
|
-
each(children)
|
|
193
|
-
|
|
194
|
-
// Code('// FILE END: ' + props.name + '\n')
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const Copy = cmp(function Copy(props: any, children: any) {
|
|
199
|
-
props.ctx$.node.kind = 'file'
|
|
200
|
-
props.ctx$.node.name = props.name
|
|
201
|
-
|
|
202
|
-
const content = props.ctx$.fs.readFileSync(props.from).toString()
|
|
203
|
-
Code(content)
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const Project: Component = cmp(function Project(props: any, children: any) {
|
|
209
|
-
props.ctx$.node.kind = 'project'
|
|
210
|
-
props.ctx$.node.name = props.name
|
|
211
|
-
|
|
212
|
-
each(children)
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
const Folder = cmp(function Folder(props: any, children: any) {
|
|
217
|
-
props.ctx$.node.kind = 'folder'
|
|
218
|
-
props.ctx$.node.name = props.name
|
|
219
|
-
|
|
220
|
-
each(children)
|
|
221
|
-
})
|
|
222
|
-
|
|
223
|
-
|
|
224
180
|
function cmp(component: Function): Component {
|
|
225
181
|
const cf = (props: any, children?: any) => {
|
|
226
182
|
props = props || {}
|
|
@@ -230,9 +186,10 @@ function cmp(component: Function): Component {
|
|
|
230
186
|
props.ctx$ = GLOBAL.jostraca.getStore()
|
|
231
187
|
children = 'function' === typeof children ? [children] : children
|
|
232
188
|
|
|
233
|
-
let node = {
|
|
189
|
+
let node: Node = {
|
|
234
190
|
kind: 'none',
|
|
235
|
-
children: []
|
|
191
|
+
children: [],
|
|
192
|
+
path: [],
|
|
236
193
|
}
|
|
237
194
|
|
|
238
195
|
const parent = props.ctx$.node = (props.ctx$.node || node)
|
|
@@ -242,6 +199,13 @@ function cmp(component: Function): Component {
|
|
|
242
199
|
props.ctx$.children = node.children
|
|
243
200
|
props.ctx$.node = node
|
|
244
201
|
|
|
202
|
+
node.path = parent.path.slice(0)
|
|
203
|
+
if ('string' === typeof props.name) {
|
|
204
|
+
node.path.push(props.name)
|
|
205
|
+
// console.log('CMP-PATH', component.name, node.path)
|
|
206
|
+
// console.trace()
|
|
207
|
+
}
|
|
208
|
+
|
|
245
209
|
let out = component(props, children)
|
|
246
210
|
|
|
247
211
|
props.ctx$.children = siblings
|
|
@@ -254,238 +218,12 @@ function cmp(component: Function): Component {
|
|
|
254
218
|
}
|
|
255
219
|
|
|
256
220
|
|
|
257
|
-
function each(subject?: any, apply?: any) {
|
|
258
|
-
if (null == apply) {
|
|
259
|
-
let out = []
|
|
260
|
-
if (Array.isArray(subject)) {
|
|
261
|
-
for (let fn of subject) {
|
|
262
|
-
out.push('function' === typeof fn ? fn() : fn)
|
|
263
|
-
}
|
|
264
|
-
return out.sort()
|
|
265
|
-
}
|
|
266
|
-
else if (null == subject || 'object' !== typeof subject) {
|
|
267
|
-
return []
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
else if (Array.isArray(subject)) {
|
|
271
|
-
return subject.map(apply)
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (null == subject || 'object' !== typeof subject) {
|
|
275
|
-
return []
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const entries: any = Object.entries(subject).map((n: any[], _: any) =>
|
|
279
|
-
(_ = typeof n[1],
|
|
280
|
-
(null != n[1] && 'object' === _) ? (n[1].key$ = n[0]) :
|
|
281
|
-
(n[1] = { name: n[0], key$: n[0], val$: n[1] }), n))
|
|
282
|
-
|
|
283
|
-
if (1 < entries.length) {
|
|
284
|
-
if (entries[0] && entries[0][1] && 'string' === typeof entries[0][1].name) {
|
|
285
|
-
entries.sort((a: any, b: any) =>
|
|
286
|
-
a[1].name < b[1].name ? -1 : b[1].name < a[1].name ? 1 : 0)
|
|
287
|
-
}
|
|
288
|
-
else if (entries[0] && entries[0][1] && 'string' === typeof entries[0][1].key$) {
|
|
289
|
-
entries.sort((a: any, b: any) =>
|
|
290
|
-
a[1].key$ < b[1].key$ ? -1 : b[1].key$ < a[1].key$ ? 1 : 0)
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
apply = 'function' === typeof apply ? apply : (x: any) => x
|
|
295
|
-
|
|
296
|
-
return entries.map((n: any, ...args: any[]) =>
|
|
297
|
-
apply(n[1], n[0], ...args))
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
function select(key: any, map: Record<string, Function>) {
|
|
303
|
-
const fn = map && map[key]
|
|
304
|
-
return fn ? fn() : undefined
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
function getx(root: any, path: string | string[]): any {
|
|
310
|
-
path = ('string' === typeof path ? path.split(/[.\s\r\n\t]/) : path).filter(part => '' != part)
|
|
311
|
-
let node = root
|
|
312
|
-
let parents = []
|
|
313
|
-
|
|
314
|
-
partloop:
|
|
315
|
-
for (let i = 0; i < path.length && null != node; i++) {
|
|
316
|
-
let part = String(path[i]).trim()
|
|
317
|
-
let m = part.match(/^([^<=>~^?!]*)([<=>~^?!]+)(.*)$/)
|
|
318
|
-
|
|
319
|
-
if (m) {
|
|
320
|
-
part = m[1]
|
|
321
|
-
let op = m[2]
|
|
322
|
-
let arg = m[3]
|
|
323
|
-
|
|
324
|
-
let val = '' === part ? node : node[part]
|
|
325
|
-
|
|
326
|
-
if ('=' === op && 'null' === arg) {
|
|
327
|
-
parents.push(node)
|
|
328
|
-
node = {} // virtual node so that ^ works consistently
|
|
329
|
-
continue partloop
|
|
330
|
-
}
|
|
331
|
-
else if ('^' === op && '' === part && '' !== arg) {
|
|
332
|
-
node = parents[parents.length - Number(arg)]
|
|
333
|
-
continue partloop
|
|
334
|
-
}
|
|
335
|
-
else if ('?' === op[0]) {
|
|
336
|
-
arg = (1 < op.length ? op.substring(1) : '') + arg
|
|
337
|
-
node = Array.isArray(val) ?
|
|
338
|
-
each(val).filter((n: any) => (
|
|
339
|
-
null != getx(n, arg))) :
|
|
340
|
-
each(val).filter((n: any) => (
|
|
341
|
-
null != getx(n, arg)))
|
|
342
|
-
.reduce((a: any, n: any) => (a[n.key$] = n, delete n.key$, a), {})
|
|
343
|
-
|
|
344
|
-
continue partloop
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
if (null == val) return undefined
|
|
348
|
-
|
|
349
|
-
val = Array.isArray(val) ? val.length :
|
|
350
|
-
'object' === typeof val ? Object.keys(val).filter(k => !k.includes('$')).length :
|
|
351
|
-
val
|
|
352
|
-
|
|
353
|
-
switch (op) {
|
|
354
|
-
case '<':
|
|
355
|
-
if (!(val < arg)) return undefined
|
|
356
|
-
break
|
|
357
|
-
case '<=':
|
|
358
|
-
if (!(val <= arg)) return undefined
|
|
359
|
-
break
|
|
360
|
-
case '>':
|
|
361
|
-
if (!(val > arg)) return undefined
|
|
362
|
-
break
|
|
363
|
-
case '>=':
|
|
364
|
-
if (!(val >= arg)) return undefined
|
|
365
|
-
break
|
|
366
|
-
case '=':
|
|
367
|
-
if (!(val == arg)) return undefined
|
|
368
|
-
break
|
|
369
|
-
case '!=':
|
|
370
|
-
if (!(val != arg)) return undefined
|
|
371
|
-
break
|
|
372
|
-
case '~':
|
|
373
|
-
if (!(String(val).match(RegExp(arg)))) return undefined
|
|
374
|
-
break
|
|
375
|
-
case '^':
|
|
376
|
-
node = parents[parents.length - Number(arg)]
|
|
377
|
-
continue partloop
|
|
378
|
-
default:
|
|
379
|
-
return undefined
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
parents.push(node)
|
|
384
|
-
node = '' === part ? node : node[part]
|
|
385
|
-
}
|
|
386
|
-
return node
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
function get(root: any, path: string | string[]): any {
|
|
391
|
-
path = 'string' === typeof path ? path.split('.') : path
|
|
392
|
-
let node = root
|
|
393
|
-
for (let i = 0; i < path.length && null != node; i++) {
|
|
394
|
-
node = node[path[i]]
|
|
395
|
-
}
|
|
396
|
-
return node
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
function camelify(input: any[] | string) {
|
|
401
|
-
let parts = 'string' == typeof input ? input.split('-') : input.map(n => '' + n)
|
|
402
|
-
return parts
|
|
403
|
-
.map((p: string) => ('' === p ? '' : (p[0].toUpperCase() + p.substring(1))))
|
|
404
|
-
.join('')
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
function kebabify(input: any[] | string) {
|
|
409
|
-
let parts = 'string' == typeof input ? input.split(/([A-Z])/) : input.map(n => '' + n)
|
|
410
|
-
return parts
|
|
411
|
-
.filter((p: string) => '' !== p)
|
|
412
|
-
.reduce((a: any[], n: string, i: number) =>
|
|
413
|
-
((0 === i % 2 ? a.push(n.toLowerCase()) : a[(i / 2) | 0] += n), a), [])
|
|
414
|
-
.join('-')
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
function snakify(input: any[] | string) {
|
|
419
|
-
let parts = 'string' == typeof input ? input.split(/([A-Z])/) : input.map(n => '' + n)
|
|
420
|
-
return parts
|
|
421
|
-
.filter((p: string) => '' !== p)
|
|
422
|
-
.reduce((a: any[], n: string, i: number) =>
|
|
423
|
-
((0 === i % 2 ? a.push(n.toLowerCase()) : a[(i / 2) | 0] += n), a), [])
|
|
424
|
-
.join('_')
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
function names(base: any, name: string, prop = 'name') {
|
|
429
|
-
base.name$ = name
|
|
430
|
-
base[prop.toLowerCase()] = name.toLowerCase()
|
|
431
|
-
base[camelify(prop)] = camelify(name)
|
|
432
|
-
base[snakify(prop)] = snakify(name)
|
|
433
|
-
base[kebabify(prop)] = kebabify(name)
|
|
434
|
-
base[prop.toUpperCase()] = name.toUpperCase()
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
// Map child objects to new child objects
|
|
440
|
-
function cmap(o: any, p: any) {
|
|
441
|
-
return Object
|
|
442
|
-
.entries(o)
|
|
443
|
-
.reduce((r: any, n: any, _: any) => (_ = Object
|
|
444
|
-
.entries(p)
|
|
445
|
-
.reduce((s: any, m: any) => (cmap.FILTER === s ? s : (s[m[0]] = (
|
|
446
|
-
// transfom(val,key,current,parentkey,parent)
|
|
447
|
-
'function' === typeof m[1] ? m[1](n[1][m[0]], {
|
|
448
|
-
skey: m[0], self: n[1], key: n[0], parent: o
|
|
449
|
-
}) : m[1]
|
|
450
|
-
), (cmap.FILTER === s[m[0]] ? cmap.FILTER : s))), {})
|
|
451
|
-
, (cmap.FILTER === _ ? 0 : r[n[0]] = _), r), {})
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
cmap.COPY = (x: any) => x
|
|
455
|
-
// keep self if x is truthy, or function returning truthy-new-value or [truthy,new-value]
|
|
456
|
-
cmap.FILTER = (x: any) => 'function' === typeof x ? ((y: any, p: any, _: any) =>
|
|
457
|
-
(_ = x(y, p), Array.isArray(_) ? !_[0] ? _[1] : cmap.FILTER : _)) : (x ? x : cmap.FILTER)
|
|
458
|
-
cmap.KEY = (_: any, p: any) => p.key
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
// Map child objects to a list of child objects
|
|
462
|
-
function vmap(o: any, p: any) {
|
|
463
|
-
return Object
|
|
464
|
-
.entries(o)
|
|
465
|
-
.reduce((r: any, n: any, _: any) => (_ = Object
|
|
466
|
-
.entries(p)
|
|
467
|
-
.reduce((s: any, m: any) => (vmap.FILTER === s ? s : (s[m[0]] = (
|
|
468
|
-
// transfom(val,key,current,parentkey,parent)
|
|
469
|
-
// 'function' === typeof m[1] ? m[1](n[1][m[0]], m[0], n[1], n[0], o) : m[1]
|
|
470
|
-
'function' === typeof m[1] ? m[1](n[1][m[0]], {
|
|
471
|
-
skey: m[0], self: n[1], key: n[0], parent: o
|
|
472
|
-
}) : m[1]
|
|
473
|
-
), (vmap.FILTER === s[m[0]] ? vmap.FILTER : s))), {})
|
|
474
|
-
, (vmap.FILTER === _ ? 0 : r.push(_)), r), [])
|
|
475
|
-
|
|
476
|
-
}
|
|
477
|
-
vmap.COPY = (x: any) => x
|
|
478
|
-
vmap.FILTER = (x: any) => 'function' === typeof x ? ((y: any, p: any, _: any) =>
|
|
479
|
-
(_ = x(y, p), Array.isArray(_) ? !_[0] ? _[1] : vmap.FILTER : _)) : (x ? x : vmap.FILTER)
|
|
480
|
-
vmap.KEY = (_: any, p: any) => p.key
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
221
|
|
|
485
222
|
|
|
486
223
|
export type {
|
|
487
224
|
JostracaOptions,
|
|
488
225
|
Component,
|
|
226
|
+
Node,
|
|
489
227
|
}
|
|
490
228
|
|
|
491
229
|
|
|
@@ -505,7 +243,7 @@ export {
|
|
|
505
243
|
names,
|
|
506
244
|
|
|
507
245
|
Project,
|
|
508
|
-
|
|
246
|
+
Content,
|
|
509
247
|
File,
|
|
510
248
|
Folder,
|
|
511
249
|
Copy,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import type { Node } from '../jostraca'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const ContentOp = {
|
|
7
|
+
before(node: Node, _ctx$: any, buildctx: any) {
|
|
8
|
+
const content = buildctx.current.content = node
|
|
9
|
+
buildctx.current.file.content.push(content.content)
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
after(_node: Node, _ctx$: any, buildctx: any) { },
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
ContentOp
|
|
18
|
+
}
|