1 | 'use strict'
|
2 |
|
3 | const Mdx = require('./index')
|
4 | const usePreludes = require('./filters/preludes')
|
5 | const useFormat = require('./filters/format')
|
6 | const normalize = require('./md_block').normalize
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | class Context {
|
13 | constructor (fname, src) {
|
14 | const lang = Mdx.detectLanguage(fname)
|
15 | if (!lang) throw new Error(`Unknown language for '${fname}'`)
|
16 |
|
17 |
|
18 | this.filename = fname
|
19 |
|
20 |
|
21 | this.src = src
|
22 |
|
23 |
|
24 | this.block = undefined
|
25 |
|
26 |
|
27 | this.blocks = []
|
28 |
|
29 |
|
30 | this.language = lang
|
31 |
|
32 |
|
33 | this.rules = this.language.rules()
|
34 | }
|
35 |
|
36 | |
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | flush () {
|
44 | this.finalizeBlock()
|
45 | this.block = this.newBlock()
|
46 | }
|
47 |
|
48 | |
49 |
|
50 |
|
51 |
|
52 | finalizeBlock () {
|
53 | if (this.block && this.block.location.doc.start !== null) {
|
54 | this.block.raw = this.block._rawlines.join('\n') + '\n'
|
55 | delete this.block._rawlines
|
56 |
|
57 |
|
58 | this.block = usePreludes(this.block, this)
|
59 | this.block = useFormat(this.block, this)
|
60 |
|
61 | this.block.markdown = normalize(this.block.raw, { lang: this.language.slug() })
|
62 |
|
63 |
|
64 | if (!this.block) return
|
65 |
|
66 |
|
67 | if (!this.block.explicit && !this.block.title) return
|
68 |
|
69 | this.blocks.push(this.block)
|
70 | }
|
71 | }
|
72 |
|
73 | |
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 | newBlock () {
|
80 | return {
|
81 | location: {
|
82 | file: this.filename,
|
83 | doc: { start: null, end: null },
|
84 | code: { start: null }
|
85 | },
|
86 | _rawlines: []
|
87 | }
|
88 | }
|
89 |
|
90 | |
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 | process () {
|
99 | const ctx = this
|
100 | ctx.flush()
|
101 |
|
102 | eachLine(ctx.src, function (line, i) {
|
103 | ctx.rules.switch(line, {
|
104 |
|
105 |
|
106 | docshort (m) {
|
107 | return
|
108 | },
|
109 |
|
110 |
|
111 | docstartex (m) {
|
112 | ctx.flush()
|
113 | ctx.block.location.doc.start = i + 1
|
114 | if (m.doc) ctx.block._rawlines.push(m.doc)
|
115 | ctx.block.explicit = true
|
116 | },
|
117 |
|
118 |
|
119 | docstart (m) {
|
120 | ctx.flush()
|
121 | ctx.block.location.doc.start = i + 1
|
122 | if (m.doc) ctx.block._rawlines.push(m.doc)
|
123 | },
|
124 |
|
125 |
|
126 |
|
127 | docend (m) {
|
128 | if (ctx.block.location.doc.end !== null) return
|
129 | ctx.block.location.doc.end = i + 1
|
130 | },
|
131 |
|
132 |
|
133 | doc (m) {
|
134 | ctx.block._rawlines.push(m.doc)
|
135 | },
|
136 |
|
137 |
|
138 |
|
139 | else (m) {
|
140 | if (ctx.block.prelude) return
|
141 |
|
142 | line = line.trim()
|
143 | if (line === '') return
|
144 | ctx.block.prelude = line
|
145 | ctx.block.location.code.start = i + 1
|
146 | }
|
147 | })
|
148 | })
|
149 |
|
150 | ctx.finalizeBlock()
|
151 | }
|
152 | }
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 | function eachLine (src, fn) {
|
159 | src.split('\n').forEach(fn)
|
160 | }
|
161 |
|
162 | module.exports = Context
|