@podlite/to-jsx 0.0.16 → 0.0.18
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/CHANGELOG.md +37 -1
- package/README.md +41 -1
- package/index.js +1 -1
- package/jest.config.js +0 -1
- package/jest.tsconfig.json +1 -1
- package/lib/index.d.ts +4 -5
- package/lib/index.js +129 -145
- package/lib/index.js.map +1 -1
- package/package.json +12 -9
- package/src/index.tsx +458 -358
- package/t/fixtures.component.spec.tsx +27 -46
- package/t/index.component.spec.tsx +83 -83
- package/tsconfig.json +6 -2
- package/tsconfig.tsbuildinfo +1 -1
package/src/index.tsx
CHANGED
|
@@ -1,184 +1,225 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import {createElement} from 'react'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
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'
|
|
7
26
|
|
|
8
27
|
// interface SetFn { <T>(<T>node, ctx:any) => () => () =>void
|
|
9
28
|
// }
|
|
10
29
|
export type CreateElement = typeof React.createElement
|
|
11
|
-
const helperMakeReact = ({wrapElement}:{wrapElement?:WrapElement})=>{
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return `${type_idx}_${mapByType[type_idx]}`
|
|
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
|
|
19
37
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
|
26
47
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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)
|
|
32
53
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
54
|
+
// // create react element and pass key
|
|
55
|
+
// if (!isValidElementType(src)) {
|
|
56
|
+
// throw new Error(`Bad React element for ${ruleName} rule `)
|
|
57
|
+
// }
|
|
37
58
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
return result
|
|
59
|
+
if (typeof wrapElement === 'function') {
|
|
60
|
+
return wrapElement(node, result, ctx)
|
|
42
61
|
}
|
|
43
|
-
|
|
62
|
+
return result
|
|
63
|
+
}
|
|
64
|
+
}
|
|
44
65
|
|
|
45
|
-
export interface
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
children: React.ReactChild,
|
|
49
|
-
ctx: any
|
|
50
|
-
) : JSX.Element
|
|
51
|
-
}
|
|
66
|
+
export interface WrapElement {
|
|
67
|
+
(node: PodNode, children: React.ReactChild, ctx: any): JSX.Element
|
|
68
|
+
}
|
|
52
69
|
export const Podlite: React.FC<{
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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)
|
|
62
87
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const handleNested = ( defaultHandler, implicitLevel?:number ) => {
|
|
74
|
-
|
|
75
|
-
return ( writer, processor ) => {
|
|
76
|
-
const defaultHandlerInited = defaultHandler( writer, processor )
|
|
77
|
-
return ( node, ctx, interator ) => {
|
|
78
|
-
|
|
79
|
-
const nesting = makeAttrs(node, ctx).getFirstValue('nested') || implicitLevel
|
|
80
|
-
const children = defaultHandlerInited( node, ctx, interator )
|
|
81
|
-
// if no nesting needs - simply return children
|
|
82
|
-
if (!nesting) {return children }
|
|
83
|
-
const arr = [...Array(nesting).keys()]
|
|
84
|
-
return arr.reduce((acc)=>makeComponent('blockquote', node, acc), children)
|
|
85
|
-
|
|
86
|
-
}
|
|
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
|
|
87
98
|
}
|
|
99
|
+
const arr = [...Array(nesting).keys()]
|
|
100
|
+
return arr.reduce(acc => makeComponent('blockquote', node, acc), children)
|
|
101
|
+
}
|
|
88
102
|
}
|
|
103
|
+
}
|
|
89
104
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
105
|
+
return {
|
|
106
|
+
pod: mkComponent('div'),
|
|
107
|
+
root: nodeContent,
|
|
108
|
+
data: emptyContent(),
|
|
94
109
|
':ambient': emptyContent(),
|
|
95
|
-
':code': mkComponent(({ children, key })
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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} />)
|
|
100
123
|
}),
|
|
101
124
|
|
|
102
|
-
':text':(
|
|
103
|
-
|
|
125
|
+
':text': (writer, processor) => (node: Text, ctx, interator) => {
|
|
126
|
+
return node.value
|
|
104
127
|
},
|
|
105
|
-
':verbatim'
|
|
106
|
-
|
|
128
|
+
':verbatim': (writer, processor) => (node: Verbatim, ctx, interator) => {
|
|
129
|
+
return node.value
|
|
107
130
|
},
|
|
108
|
-
'head:block': subUse(
|
|
131
|
+
'head:block': subUse(
|
|
132
|
+
{
|
|
109
133
|
// inside head don't wrap into <p>
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
+
),
|
|
118
142
|
|
|
119
143
|
':blankline': emptyContent(),
|
|
120
|
-
':para'
|
|
121
|
-
|
|
144
|
+
':para': mkComponent('p'),
|
|
145
|
+
para: mkComponent('div'),
|
|
122
146
|
'comment:block': emptyContent(),
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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,
|
|
130
155
|
),
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
+
)),
|
|
134
167
|
|
|
135
|
-
// Directives
|
|
136
|
-
':config': setFn((
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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()
|
|
148
182
|
}),
|
|
149
183
|
|
|
150
184
|
// Formatting codes
|
|
151
|
-
'A<>': (
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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<{children}></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)
|
|
159
204
|
} else {
|
|
160
|
-
|
|
161
|
-
const tree_1 = processor( src )
|
|
162
|
-
// now clean locations
|
|
163
|
-
const tree = clean_plugin()(tree_1)
|
|
164
|
-
if ( tree[0].type === 'para') {
|
|
165
|
-
return interator( tree[0].content, ctx )
|
|
166
|
-
} else {
|
|
167
|
-
return interator( tree, ctx )
|
|
168
|
-
}
|
|
205
|
+
return interator(tree, ctx)
|
|
169
206
|
}
|
|
207
|
+
}
|
|
170
208
|
},
|
|
171
209
|
'B<>': mkComponent('strong'),
|
|
172
210
|
'C<>': mkComponent('code'),
|
|
173
|
-
'E<>': (
|
|
174
|
-
|
|
175
|
-
return node.content
|
|
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 => {
|
|
176
216
|
return String.fromCharCode(element.value)
|
|
177
|
-
|
|
217
|
+
})
|
|
218
|
+
.join('')
|
|
178
219
|
},
|
|
179
220
|
'I<>': mkComponent('i'),
|
|
180
221
|
'K<>': mkComponent('kbd'),
|
|
181
|
-
|
|
222
|
+
/**
|
|
182
223
|
* CSS rules for footnotes
|
|
183
224
|
|
|
184
225
|
.footnote a {
|
|
@@ -190,258 +231,317 @@ const mapToReact = (makeComponent):Partial<RulesStrict> => {
|
|
|
190
231
|
border-top-color: #eee;
|
|
191
232
|
}
|
|
192
233
|
*/
|
|
193
|
-
'N<>'
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if ( footnotes.length < 1 ) { return } // if empty footnotes
|
|
198
|
-
if ( !writer.hasOwnProperty('postInterator') ) { writer.postInterator = []}
|
|
199
|
-
|
|
200
|
-
const FootNotes = makeComponent(({children, key})=><div key={`${key}_FOOTNOTES`} className="footnotes">
|
|
201
|
-
{
|
|
202
|
-
footnotes.map((footnote, id) =>{
|
|
203
|
-
return <p key={id}>
|
|
204
|
-
<sup id={footnote.fnId} className="footnote"><a href={`#${footnote.fnRefId}`}>[{footnote.gid}]</a></sup>
|
|
205
|
-
{ footnote.make() }
|
|
206
|
-
</p>
|
|
207
|
-
})
|
|
208
|
-
}
|
|
209
|
-
</div>,{})
|
|
210
|
-
|
|
211
|
-
writer.postInterator.push( FootNotes )
|
|
212
|
-
|
|
213
|
-
})
|
|
214
|
-
return ( node, ctx, interator ) => {
|
|
215
|
-
// skip empty notes
|
|
216
|
-
if ( node.content.length < 1 ) { return }
|
|
217
|
-
if ( !writer.hasOwnProperty('gid') ) { writer.gid = 1}
|
|
218
|
-
// get foot note id
|
|
219
|
-
const gid = writer.gid++
|
|
220
|
-
const fnRefId = `fnref:${gid}`
|
|
221
|
-
const fnId = `fn:${gid}`
|
|
222
|
-
if ( !writer.hasOwnProperty('FOOTNOTES') ) { writer.FOOTNOTES = []}
|
|
223
|
-
writer.FOOTNOTES.push({
|
|
224
|
-
gid,
|
|
225
|
-
fnRefId,
|
|
226
|
-
fnId,
|
|
227
|
-
node,
|
|
228
|
-
make: ( )=>{ return interator(node.content, ctx) }
|
|
229
|
-
})
|
|
230
|
-
return makeComponent(({children, key})=><sup key={key} id={fnRefId} className="footnote"><a href={`#${fnId}`}>[{gid}]</a></sup> , node )
|
|
234
|
+
'N<>': (writer, processor) => {
|
|
235
|
+
writer.addListener('end', () => {
|
|
236
|
+
if (!writer.hasOwnProperty('FOOTNOTES')) {
|
|
237
|
+
return
|
|
231
238
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
let definition:string[] = [node.content[0]]
|
|
239
|
-
if ( synonyms ) {
|
|
240
|
-
definition = synonyms
|
|
239
|
+
const footnotes = writer.FOOTNOTES
|
|
240
|
+
if (footnotes.length < 1) {
|
|
241
|
+
return
|
|
242
|
+
} // if empty footnotes
|
|
243
|
+
if (!writer.hasOwnProperty('postInterator')) {
|
|
244
|
+
writer.postInterator = []
|
|
241
245
|
}
|
|
242
246
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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
|
|
255
271
|
}
|
|
256
|
-
if (
|
|
257
|
-
|
|
272
|
+
if (!writer.hasOwnProperty('gid')) {
|
|
273
|
+
writer.gid = 1
|
|
258
274
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
if (
|
|
264
|
-
|
|
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 = []
|
|
265
281
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
282
|
+
writer.FOOTNOTES.push({
|
|
283
|
+
gid,
|
|
284
|
+
fnRefId,
|
|
285
|
+
fnId,
|
|
286
|
+
node,
|
|
287
|
+
make: () => {
|
|
288
|
+
return interator(node.content, ctx)
|
|
289
|
+
},
|
|
270
290
|
})
|
|
271
|
-
return makeComponent(
|
|
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)
|
|
272
345
|
},
|
|
273
346
|
'V<>': nodeContent,
|
|
274
347
|
'Z<>': emptyContent(),
|
|
275
348
|
'U<>': mkComponent('u'),
|
|
276
|
-
'X<>'
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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
|
+
},
|
|
289
364
|
'Delete<>': mkComponent('del'),
|
|
290
365
|
// table section
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
,
|
|
316
|
-
':separator' : emptyContent(),
|
|
317
|
-
'table_row' : mkComponent('tr'),
|
|
318
|
-
'table_cell': mkComponent('td'),
|
|
319
|
-
'table_head' : subUse(
|
|
320
|
-
{
|
|
321
|
-
'table_cell': mkComponent('th')
|
|
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
|
+
)
|
|
322
389
|
},
|
|
323
|
-
|
|
324
|
-
),
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
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 })
|
|
344
420
|
},
|
|
345
421
|
// table of content
|
|
346
|
-
':toc': setFn((
|
|
347
|
-
|
|
348
|
-
|
|
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
|
+
))
|
|
349
430
|
}),
|
|
350
|
-
':toc-list': setFn((
|
|
351
|
-
|
|
352
|
-
|
|
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
|
+
))
|
|
353
438
|
}),
|
|
354
|
-
':toc-item': subUse(
|
|
439
|
+
':toc-item': subUse(
|
|
440
|
+
{
|
|
355
441
|
// inside head don't wrap into <p>
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
return mkComponent(({children, key })
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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
|
+
}
|
|
363
453
|
}
|
|
364
|
-
function
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
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)
|
|
372
470
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
471
|
+
// const ast = parse( children || content )
|
|
472
|
+
let i_key_i = 10000
|
|
473
|
+
const makeComponent = helperMakeReact({ wrapElement })
|
|
376
474
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
...jsxPluginInited,
|
|
386
|
-
}
|
|
387
|
-
interface WriterPostinterator extends Writer {
|
|
388
|
-
postInterator? : any
|
|
389
|
-
}
|
|
390
|
-
const writer = new Writer((s)=>{
|
|
391
|
-
}) as WriterPostinterator
|
|
392
|
-
const res =
|
|
393
|
-
toAny({processor:parse})
|
|
394
|
-
.use({'*:*':() => ( node, ctx, interator ) => {
|
|
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
|
+
)
|
|
395
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) => {
|
|
396
496
|
// skip named blocks
|
|
397
497
|
if (isNamedBlock(node.name)) {
|
|
398
|
-
|
|
498
|
+
return null
|
|
399
499
|
}
|
|
400
|
-
if (
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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 })}
|
|
404
509
|
</div>
|
|
405
|
-
|
|
510
|
+
)
|
|
511
|
+
},
|
|
512
|
+
node,
|
|
513
|
+
interator(node.content, { ...ctx }),
|
|
514
|
+
)
|
|
406
515
|
}
|
|
407
|
-
console.warn('[podlite] Not supported: ' + JSON.stringify(node,null,2))
|
|
408
|
-
return createElement('code',{key
|
|
409
|
-
|
|
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
|
+
})
|
|
410
520
|
.use(rules)
|
|
411
521
|
.run(ast, writer)
|
|
412
|
-
// union main react elements and post processed via onEnd event
|
|
413
|
-
return new Array().concat(
|
|
522
|
+
// union main react elements and post processed via onEnd event
|
|
523
|
+
return new Array().concat(res.interator, writer.postInterator)
|
|
414
524
|
}
|
|
415
525
|
|
|
416
526
|
// this is a helper function for using in unit test
|
|
417
527
|
export const TestPodlite = ({ children, ...options }) => {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
// its replace all ids with "id"
|
|
421
|
-
let treeAfterParsed = frozenIds()(podlite.parse(children));
|
|
422
|
-
|
|
423
|
-
const tree = podlite.toAst(treeAfterParsed);
|
|
424
|
-
return (
|
|
425
|
-
<Podlite
|
|
426
|
-
{...{ children, ...options, tree: { interator: tree } as PodliteExport }}
|
|
427
|
-
/>
|
|
428
|
-
);
|
|
429
|
-
};
|
|
430
|
-
|
|
431
|
-
export const makeTestPodlite = (podlite = podlite_core({ importPlugins: true })) => ({ children, ...options }) => {
|
|
528
|
+
let podlite = podlite_core({ importPlugins: true })
|
|
432
529
|
|
|
433
|
-
|
|
530
|
+
// its replace all ids with "id"
|
|
531
|
+
let treeAfterParsed = frozenIds()(podlite.parse(children))
|
|
434
532
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
<Podlite
|
|
439
|
-
{...{ children, ...options, tree: { interator: tree } as PodliteExport }}
|
|
440
|
-
/>
|
|
441
|
-
);
|
|
442
|
-
};
|
|
443
|
-
|
|
533
|
+
const tree = podlite.toAst(treeAfterParsed)
|
|
534
|
+
return <Podlite {...{ children, ...options, tree: { interator: tree } as PodliteExport }} />
|
|
535
|
+
}
|
|
444
536
|
|
|
445
|
-
export
|
|
537
|
+
export const makeTestPodlite =
|
|
538
|
+
(podlite = podlite_core({ importPlugins: true })) =>
|
|
539
|
+
({ children, ...options }) => {
|
|
540
|
+
let treeAfterParsed = podlite.parse(children)
|
|
446
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
|
+
}
|
|
447
546
|
|
|
547
|
+
export default Podlite
|