@podlite/to-jsx 0.0.18 → 0.0.20

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/src/index.tsx DELETED
@@ -1,547 +0,0 @@
1
- import * as React from 'react'
2
- import { createElement } from 'react'
3
- import { podlite as podlite_core } from 'podlite'
4
- import {
5
- Verbatim,
6
- PodNode,
7
- Text,
8
- Rules,
9
- RulesStrict,
10
- getNodeId,
11
- parse,
12
- makeAttrs,
13
- emptyContent,
14
- content as nodeContent,
15
- setFn,
16
- subUse,
17
- toAny,
18
- isNamedBlock,
19
- isSemanticBlock,
20
- Writer,
21
- toAnyRules,
22
- PodliteExport,
23
- frozenIds,
24
- } from '@podlite/schema'
25
- import { Toc, Plugin, pluginCleanLocation as clean_plugin } from '@podlite/schema'
26
-
27
- // interface SetFn { <T>(<T>node, ctx:any) => () => () =>void
28
- // }
29
- export type CreateElement = typeof React.createElement
30
- const helperMakeReact = ({ wrapElement }: { wrapElement?: WrapElement }) => {
31
- let i_key_i = 0
32
- let mapByType = {}
33
- const getIdForNode = ({ type = 'notype', name = 'noname' }) => {
34
- const type_idx = `${type}_${name}`
35
- if (!mapByType[type_idx]) {
36
- mapByType[type_idx] = 0
37
- }
38
- ++mapByType[type_idx]
39
- return `${type_idx}_${mapByType[type_idx]}`
40
- }
41
- return function (src: string | Function, node: PodNode, children, extraProps = {}, ctx = {}) {
42
- // for string return it
43
- if (typeof node == 'string') {
44
- return node
45
- }
46
- const { ...attr } = node
47
-
48
- const key = 'type' in node && node.type ? getIdForNode(node) : ++i_key_i
49
- const result =
50
- typeof src === 'function'
51
- ? src({ ...attr, key, children }, children)
52
- : createElement(src, { ...extraProps, key }, children)
53
-
54
- // // create react element and pass key
55
- // if (!isValidElementType(src)) {
56
- // throw new Error(`Bad React element for ${ruleName} rule `)
57
- // }
58
-
59
- if (typeof wrapElement === 'function') {
60
- return wrapElement(node, result, ctx)
61
- }
62
- return result
63
- }
64
- }
65
-
66
- export interface WrapElement {
67
- (node: PodNode, children: React.ReactChild, ctx: any): JSX.Element
68
- }
69
- export const Podlite: React.FC<{
70
- [key: string]: any
71
- children?: string
72
- file?: string
73
- plugins?: any
74
- wrapElement?: WrapElement
75
- tree?: PodliteExport
76
- }> = ({ children, ...options }) => {
77
- const result: any = podlite(children, options)
78
- return result
79
- }
80
- const mapToReact = (makeComponent): Partial<RulesStrict> => {
81
- const mkComponent = src => (writer, processor) => (node, ctx, interator) => {
82
- // prepare extraProps for createElement
83
- // add id attribute if exists
84
- const id = getNodeId(node, ctx)?.replace(/\s/g, '-')
85
- // check if node.content defined
86
- return makeComponent(src, node, 'content' in node ? interator(node.content, { ...ctx }) : [], { id }, ctx)
87
- }
88
- // Handle nested block and :nested block attribute
89
- const handleNested = (defaultHandler, implicitLevel?: number) => {
90
- return (writer, processor) => {
91
- const defaultHandlerInited = defaultHandler(writer, processor)
92
- return (node, ctx, interator) => {
93
- const nesting = makeAttrs(node, ctx).getFirstValue('nested') || implicitLevel
94
- const children = defaultHandlerInited(node, ctx, interator)
95
- // if no nesting needs - simply return children
96
- if (!nesting) {
97
- return children
98
- }
99
- const arr = [...Array(nesting).keys()]
100
- return arr.reduce(acc => makeComponent('blockquote', node, acc), children)
101
- }
102
- }
103
- }
104
-
105
- return {
106
- pod: mkComponent('div'),
107
- root: nodeContent,
108
- data: emptyContent(),
109
- ':ambient': emptyContent(),
110
- ':code': mkComponent(({ children, key }) => (
111
- <code key={key}>
112
- <pre>{children}</pre>
113
- </code>
114
- )),
115
- code: mkComponent(({ children, key }) => (
116
- <code key={key}>
117
- <pre>{children}</pre>
118
- </code>
119
- )),
120
- image: nodeContent,
121
- ':image': setFn((node, ctx) => {
122
- return mkComponent(({ children, key }) => <img key={key} src={node.src} alt={node.alt} />)
123
- }),
124
-
125
- ':text': (writer, processor) => (node: Text, ctx, interator) => {
126
- return node.value
127
- },
128
- ':verbatim': (writer, processor) => (node: Verbatim, ctx, interator) => {
129
- return node.value
130
- },
131
- 'head:block': subUse(
132
- {
133
- // inside head don't wrap into <p>
134
- ':para': nodeContent,
135
- },
136
- setFn((node, ctx) => {
137
- const { level } = node
138
- const id = getNodeId(node, ctx)?.replace(/\s/g, '-')
139
- return mkComponent(({ level, children, key }) => createElement(`h${level}`, { key, id }, children))
140
- }),
141
- ),
142
-
143
- ':blankline': emptyContent(),
144
- ':para': mkComponent('p'),
145
- para: mkComponent('div'),
146
- 'comment:block': emptyContent(),
147
- defn: subUse(
148
- [
149
- // to avoid overlap para blocks handlers
150
- // define general :para at first
151
- { ':para': mkComponent('dd') },
152
- { 'term:para': mkComponent('dt') },
153
- ],
154
- nodeContent,
155
- ),
156
- nested: handleNested(nodeContent, 1),
157
- output: mkComponent(({ children, key }) => (
158
- <pre key={key}>
159
- <samp>{children}</samp>
160
- </pre>
161
- )),
162
- input: mkComponent(({ children, key }) => (
163
- <pre key={key}>
164
- <kbd>{children}</kbd>
165
- </pre>
166
- )),
167
-
168
- // Directives
169
- ':config': setFn((node, ctx) => {
170
- // setup context
171
- if (!ctx.hasOwnProperty('config')) ctx.config = {}
172
- //collect configs in context
173
- ctx.config[node.name] = node.config
174
- return emptyContent()
175
- }),
176
- ':alias': setFn((node, ctx) => {
177
- // set alias
178
- if (!ctx.hasOwnProperty('alias')) ctx.alias = {}
179
- //collect configs in context
180
- ctx.alias[node.name] = node.replacement
181
- return emptyContent()
182
- }),
183
-
184
- // Formatting codes
185
- 'A<>': (writer, processor) => (node, ctx, interator) => {
186
- let term = node.content
187
- if (typeof term !== 'string' && 'value' in term) {
188
- term = term.value
189
- }
190
- //get replacement text
191
- if (!(ctx.alias && ctx.alias.hasOwnProperty(term))) {
192
- return makeComponent(
193
- ({ children, key }) => <code key={key}>A&lt;{children}&gt;</code>,
194
- node,
195
- interator(node.content, ctx),
196
- )
197
- } else {
198
- const src = ctx.alias[term].join('\n')
199
- const tree_1 = processor(src)
200
- // now clean locations
201
- const tree = clean_plugin()(tree_1)
202
- if (tree[0].type === 'para') {
203
- return interator(tree[0].content, ctx)
204
- } else {
205
- return interator(tree, ctx)
206
- }
207
- }
208
- },
209
- 'B<>': mkComponent('strong'),
210
- 'C<>': mkComponent('code'),
211
- 'E<>': (writer, processor) => (node, ctx, interator) => {
212
- if ('content' in node && Array.isArray(node.content))
213
- return node.content
214
- .filter(e => e && e.type == 'number')
215
- .map(element => {
216
- return String.fromCharCode(element.value)
217
- })
218
- .join('')
219
- },
220
- 'I<>': mkComponent('i'),
221
- 'K<>': mkComponent('kbd'),
222
- /**
223
- * CSS rules for footnotes
224
-
225
- .footnote a {
226
- text-decoration: none;
227
- }
228
- .footnotes {
229
- border-top-style: solid;
230
- border-top-width: 1px;
231
- border-top-color: #eee;
232
- }
233
- */
234
- 'N<>': (writer, processor) => {
235
- writer.addListener('end', () => {
236
- if (!writer.hasOwnProperty('FOOTNOTES')) {
237
- return
238
- }
239
- const footnotes = writer.FOOTNOTES
240
- if (footnotes.length < 1) {
241
- return
242
- } // if empty footnotes
243
- if (!writer.hasOwnProperty('postInterator')) {
244
- writer.postInterator = []
245
- }
246
-
247
- const FootNotes = makeComponent(
248
- ({ children, key }) => (
249
- <div key={`${key}_FOOTNOTES`} className="footnotes">
250
- {footnotes.map((footnote, id) => {
251
- return (
252
- <p key={id}>
253
- <sup id={footnote.fnId} className="footnote">
254
- <a href={`#${footnote.fnRefId}`}>[{footnote.gid}]</a>
255
- </sup>
256
- {footnote.make()}
257
- </p>
258
- )
259
- })}
260
- </div>
261
- ),
262
- {},
263
- )
264
-
265
- writer.postInterator.push(FootNotes)
266
- })
267
- return (node, ctx, interator) => {
268
- // skip empty notes
269
- if (node.content.length < 1) {
270
- return
271
- }
272
- if (!writer.hasOwnProperty('gid')) {
273
- writer.gid = 1
274
- }
275
- // get foot note id
276
- const gid = writer.gid++
277
- const fnRefId = `fnref:${gid}`
278
- const fnId = `fn:${gid}`
279
- if (!writer.hasOwnProperty('FOOTNOTES')) {
280
- writer.FOOTNOTES = []
281
- }
282
- writer.FOOTNOTES.push({
283
- gid,
284
- fnRefId,
285
- fnId,
286
- node,
287
- make: () => {
288
- return interator(node.content, ctx)
289
- },
290
- })
291
- return makeComponent(
292
- ({ children, key }) => (
293
- <sup key={key} id={fnRefId} className="footnote">
294
- <a href={`#${fnId}`}>[{gid}]</a>
295
- </sup>
296
- ),
297
- node,
298
- )
299
- }
300
- },
301
- 'R<>': mkComponent('var'),
302
- 'T<>': mkComponent('samp'),
303
- 'D<>': (writer, processor) => (node, ctx, interator) => {
304
- let { synonyms } = node
305
- let definition: string[] = [node.content[0]]
306
- if (synonyms) {
307
- definition = synonyms
308
- }
309
-
310
- if (!writer.hasOwnProperty('DEFINITIONS')) {
311
- writer.DEFINITIONS = []
312
- }
313
- writer.DEFINITIONS.push({ definition })
314
- return makeComponent('dfn', node, interator(node.content, ctx))
315
- },
316
- 'L<>': setFn((node, ctx) => {
317
- let { meta } = node
318
- if (meta === null) {
319
- meta = node.content
320
- }
321
- //TODO: extract text from content array
322
- if (Array.isArray(meta)) {
323
- meta = meta[0]
324
- }
325
- if (meta && typeof meta !== 'string' && 'value' in meta) {
326
- meta = meta.value
327
- }
328
- return mkComponent(({ children, key }) => (
329
- <a href={meta} key={key}>
330
- {children}
331
- </a>
332
- ))
333
- }),
334
- 'S<>': (writer, processor) => (node, ctx, interator) => {
335
- let content = node.content || ''
336
- if (typeof content !== 'string' && 'value' in content) {
337
- content = content.value
338
- }
339
- const Content = content.split('').map((symbol, index) => {
340
- if (symbol === ' ') return '\u00a0'
341
- if (symbol === '\n') return <br key={index} />
342
- return symbol
343
- })
344
- return makeComponent(({ children, key }) => children, {}, Content)
345
- },
346
- 'V<>': nodeContent,
347
- 'Z<>': emptyContent(),
348
- 'U<>': mkComponent('u'),
349
- 'X<>': (writer, processor) => (node, ctx, interator) => {
350
- let { entry } = node
351
- if (entry === null && node.content.length > 0) {
352
- //@ts-ignore
353
- entry = [node.content[0]]
354
- }
355
- // else { return }
356
- if (!writer.hasOwnProperty('INDEXTERMS')) {
357
- writer.INDEXTERMS = []
358
- }
359
- writer.INDEXTERMS.push({
360
- entry,
361
- })
362
- return interator(node.content, ctx)
363
- },
364
- 'Delete<>': mkComponent('del'),
365
- // table section
366
- table: (writer, processor) => (node, ctx, interator) => {
367
- const conf = makeAttrs(node, ctx)
368
- let attr = { caption: '' }
369
- if (conf.exists('caption')) {
370
- const caption = conf.getFirstValue('caption')
371
- attr.caption = caption
372
- }
373
- if (typeof node === 'string') {
374
- return node
375
- }
376
- if (!('content' in node)) {
377
- console.warn('[jsx] no content in node')
378
- return ''
379
- }
380
- const id = getNodeId(node, ctx)?.replace(/\s/g, '-')
381
- return makeComponent(
382
- ({ key, children }) => {
383
- return (
384
- <table key={key} id={id}>
385
- <caption className="caption">{attr.caption}</caption>
386
- <tbody>{children}</tbody>
387
- </table>
388
- )
389
- },
390
- node,
391
- interator(node.content, { ...ctx }),
392
- )
393
- },
394
- ':separator': emptyContent(),
395
- table_row: mkComponent('tr'),
396
- table_cell: mkComponent('td'),
397
- table_head: subUse(
398
- {
399
- table_cell: mkComponent('th'),
400
- },
401
- mkComponent('tr'),
402
- ),
403
- ':list': setFn((node, ctx) =>
404
- node.list === 'ordered' ? mkComponent('ol') : node.list === 'variable' ? mkComponent('dl') : mkComponent('ul'),
405
- ),
406
- 'item:block': (writer, processor) => (node, ctx, interator) => {
407
- if (typeof node === 'string') {
408
- return node
409
- }
410
- if (!('content' in node)) {
411
- console.warn('[jsx] no content in node')
412
- return ''
413
- }
414
- // make text from first para
415
- if (!(node.content instanceof Array)) {
416
- console.error(node)
417
- }
418
- const id = getNodeId(node, ctx)?.replace(/\s/g, '-')
419
- return makeComponent('li', node, interator(node.content, { ...ctx }), { id })
420
- },
421
- // table of content
422
- ':toc': setFn((node: Toc, ctx) => {
423
- const tocTitle = node.title
424
- return mkComponent(({ children, key }) => (
425
- <div className="toc" key={key}>
426
- {tocTitle ? <div className="toctitle">{tocTitle}</div> : ''}
427
- {children}
428
- </div>
429
- ))
430
- }),
431
- ':toc-list': setFn((node, ctx) => {
432
- const { level } = node
433
- return mkComponent(({ children, key }) => (
434
- <ul className={`toc-list listlevel${level}`} key={key}>
435
- {children}
436
- </ul>
437
- ))
438
- }),
439
- ':toc-item': subUse(
440
- {
441
- // inside head don't wrap into <p>
442
- ':para': nodeContent,
443
- },
444
- setFn((node, ctx) => {
445
- return mkComponent(({ children, key }) => (
446
- <li className="toc-item" key={key}>
447
- {children}
448
- </li>
449
- ))
450
- }),
451
- ),
452
- }
453
- }
454
- function podlite(
455
- children: string,
456
- {
457
- file,
458
- plugins = () => {},
459
- wrapElement,
460
- tree,
461
- }: { file?: string; plugins?: any; wrapElement?: WrapElement; tree?: PodliteExport },
462
- ...args
463
- ) {
464
- const ast = (tree => {
465
- if (tree) return tree.interator
466
- let podlite = podlite_core({ importPlugins: true })
467
- let treeAfterParsed = podlite.parse(children || file)
468
- return podlite.toAst(treeAfterParsed)
469
- })(tree)
470
-
471
- // const ast = parse( children || content )
472
- let i_key_i = 10000
473
- const makeComponent = helperMakeReact({ wrapElement })
474
-
475
- const jsxPlugins: { [name: string]: Plugin['toJSX'] } = toAnyRules(
476
- 'toJSX',
477
- podlite_core({ importPlugins: true }).getPlugins(),
478
- )
479
- // initialize each plugin
480
- const jsxPluginInited = Object.fromEntries(
481
- Object.entries(jsxPlugins).map(([key, value]) => [key, value(makeComponent)]),
482
- )
483
-
484
- const rules: Rules = {
485
- ...mapToReact(makeComponent),
486
- ...plugins(makeComponent),
487
- ...jsxPluginInited,
488
- }
489
- interface WriterPostinterator extends Writer {
490
- postInterator?: any
491
- }
492
- const writer = new Writer(s => {}) as WriterPostinterator
493
- const res = toAny({ processor: parse })
494
- .use({
495
- '*:*': () => (node, ctx, interator) => {
496
- // skip named blocks
497
- if (isNamedBlock(node.name)) {
498
- return null
499
- }
500
- if (isSemanticBlock(node)) {
501
- return makeComponent(
502
- ({ key, children }) => {
503
- return (
504
- <div key={key}>
505
- <h1 className={node.name} key={key}>
506
- {node.name}
507
- </h1>
508
- {interator(node.content, { ...ctx })}
509
- </div>
510
- )
511
- },
512
- node,
513
- interator(node.content, { ...ctx }),
514
- )
515
- }
516
- console.warn('[podlite] Not supported: ' + JSON.stringify(node, null, 2))
517
- return createElement('code', { key: ++i_key_i }, `not supported node:${JSON.stringify(node, null, 2)}`)
518
- },
519
- })
520
- .use(rules)
521
- .run(ast, writer)
522
- // union main react elements and post processed via onEnd event
523
- return new Array().concat(res.interator, writer.postInterator)
524
- }
525
-
526
- // this is a helper function for using in unit test
527
- export const TestPodlite = ({ children, ...options }) => {
528
- let podlite = podlite_core({ importPlugins: true })
529
-
530
- // its replace all ids with "id"
531
- let treeAfterParsed = frozenIds()(podlite.parse(children))
532
-
533
- const tree = podlite.toAst(treeAfterParsed)
534
- return <Podlite {...{ children, ...options, tree: { interator: tree } as PodliteExport }} />
535
- }
536
-
537
- export const makeTestPodlite =
538
- (podlite = podlite_core({ importPlugins: true })) =>
539
- ({ children, ...options }) => {
540
- let treeAfterParsed = podlite.parse(children)
541
-
542
- // its replace all ids with "id"
543
- const tree = frozenIds()(podlite.toAst(treeAfterParsed))
544
- return <Podlite {...{ children, ...options, tree: { interator: tree } as PodliteExport }} />
545
- }
546
-
547
- export default Podlite
@@ -1,165 +0,0 @@
1
- # test implicit para
2
- #---
3
- =begin pod
4
- =begin para
5
- sdsd
6
- sdasd
7
-
8
- ddsds
9
- d
10
- =end para
11
- =end pod
12
- #---
13
-
14
- # test vmargin
15
- #---
16
- =begin pod
17
- twest
18
- =for para
19
- sdsdsdsd
20
-
21
- jjj
22
- =end pod
23
- #---
24
-
25
- # test Named blocks
26
- #---
27
- =begin pod
28
- =for Named
29
- text
30
- =begin Named
31
- sdsdsdsd ssd s
32
- asdasdasdasd
33
-
34
- dd
35
- =end Named
36
-
37
- =end pod
38
- #---
39
-
40
- #---
41
- =head1 Test
42
-
43
- text
44
-
45
- =head2 Testing
46
- continue
47
-
48
- test
49
-
50
- #---
51
-
52
-
53
- # Value is... Specify with... Or with... Or with...
54
- # =============== ======================= ================= ===========
55
- # List :key[$e1,$e2,...] :key($e1,$e2,...)
56
- # Hash :key{$k1=>$v1,$k2=>$v2}
57
- # Boolean (true) :key :key(True)
58
- # Boolean (false) :!key :key(False)
59
- # String :key<str> :key('str') :key("str")
60
- # Number :key(42) :key(2.3)
61
-
62
- #---
63
- =begin table :k1<str> :k2('str') :k3("str") :k4["str"] :k5(Q[str])
64
-
65
- =end table
66
- #---
67
-
68
- #---
69
- =config table :k1<very long string, comma> :k2<2 23 23 > :k3<'23', 23233, 333>
70
- #---
71
-
72
- #---
73
- =code
74
- sdkljsalkdjlsd
75
- asdasdasdasdsad
76
- =for code
77
- sdkljsalkdjlsd
78
- asdasdasdasdsad
79
- =begin code
80
- sdkljsalkdjlsd
81
- asdasdasdasdsad
82
- =end code
83
- #---
84
-
85
- #---
86
- =config C<> :allow<B>
87
- #---
88
-
89
- #---
90
- =begin SYNOPSIS
91
- Para inside SYNOPSIS
92
- =end SYNOPSIS
93
- #---
94
-
95
- # Empty fcode #3
96
- #---
97
- =para
98
- teZ<s>tZ<>
99
- #---
100
-
101
- # N<> Footnote
102
- #---
103
- =para
104
- Use a C<for> loop instead.N<The Perl 6 C<for> loop is far more
105
- powerful than its Perl 5 predecessor.> Preferably with an explicit
106
- iterator variable.
107
- #---
108
-
109
-
110
- # X<> indexing terms
111
- #---
112
- =para
113
- A X<hash|hashes, definition of; associative arrays>
114
- is an unordered X<collection> of X<scalar|scalars> values indexed by their
115
- associated string X<|puns, deliberate> key. X<> empty
116
- #---
117
-
118
- # U<> formatting code
119
- #---
120
- =para
121
- The C<U<>> formatting code specifies that the contained text is
122
- U<unusual> or distinctive;
123
- #---
124
-
125
- # T<> and K<> formatting codes
126
- #---
127
- =para
128
- Such content would typically be rendered in a K<fixed-width font>
129
- Such content would typically be rendered in a T<fixed-width font>
130
- #---
131
-
132
- # Ambient code
133
- #---
134
- =d
135
- Such content would typically be rendered in a K<fixed-width font>
136
- Such content would typically be rendered in a T<fixed-width font>
137
- =head1 test
138
- =begin pod
139
- test
140
- e
141
- =head1 sd
142
-
143
- =end pod
144
- =head2 test
145
-
146
- ambient again
147
- #---
148
-
149
- #---
150
- =begin pod
151
- =item
152
-
153
- test
154
-
155
- =end pod
156
- #---
157
-
158
- # Empty fcode #14
159
- #---
160
- =begin code
161
- =begin item1
162
- First
163
- =end item1
164
- =end code
165
- #---