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