boxwood 2.7.0 → 2.8.2

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/ui/markdown/index.js +174 -35
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "boxwood",
3
- "version": "2.7.0",
3
+ "version": "2.8.2",
4
4
  "description": "Compile HTML templates into JS",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -1,42 +1,181 @@
1
- const { component, H1, H2, H3, H4, H5, H6, P, Blockquote } = require("../..")
1
+ const {
2
+ component,
3
+ H1,
4
+ H2,
5
+ H3,
6
+ H4,
7
+ H5,
8
+ H6,
9
+ P,
10
+ Blockquote,
11
+ Ul,
12
+ Ol,
13
+ Li,
14
+ Strong,
15
+ Em,
16
+ Code,
17
+ } = require("../..")
18
+
19
+ const ORDERED_LIST_REGEXP = /^\d+\.\s/
20
+ const UNORDERED_MARKERS = ["- ", "— ", "– ", "• "]
21
+ const HEADINGS = [
22
+ { prefix: "###### ", type: "h6" },
23
+ { prefix: "##### ", type: "h5" },
24
+ { prefix: "#### ", type: "h4" },
25
+ { prefix: "### ", type: "h3" },
26
+ { prefix: "## ", type: "h2" },
27
+ { prefix: "# ", type: "h1" },
28
+ ]
29
+ const COMPONENTS = {
30
+ h1: H1,
31
+ h2: H2,
32
+ h3: H3,
33
+ h4: H4,
34
+ h5: H5,
35
+ h6: H6,
36
+ blockquote: Blockquote,
37
+ }
38
+
39
+ function format(text) {
40
+ if (!text.includes("*") && !text.includes("`")) {
41
+ return text
42
+ }
43
+
44
+ const result = []
45
+ let i = 0
46
+ while (i < text.length) {
47
+ if (text[i] === "`") {
48
+ const start = i + 1
49
+ const end = text.indexOf("`", start)
50
+ if (end === -1) {
51
+ result.push(text[i])
52
+ i++
53
+ } else {
54
+ result.push(Code({}, text.substring(start, end)))
55
+ i = end + 1
56
+ }
57
+ } else if (text[i] === "*" && text[i + 1] === "*") {
58
+ const start = i + 2
59
+ const end = text.indexOf("**", start)
60
+ if (end === -1) {
61
+ result.push(text[i])
62
+ i++
63
+ } else {
64
+ result.push(Strong(text.substring(start, end)))
65
+ i = end + 2
66
+ }
67
+ } else if (text[i] === "*") {
68
+ const start = i + 1
69
+ const end = text.indexOf("*", start)
70
+ if (end === -1) {
71
+ result.push(text[i])
72
+ i++
73
+ } else {
74
+ result.push(Em(text.substring(start, end)))
75
+ i = end + 1
76
+ }
77
+ } else {
78
+ let next = text.length
79
+ const nextCode = text.indexOf("`", i)
80
+ const nextStar = text.indexOf("*", i)
81
+ if (nextCode !== -1 && nextCode < next) next = nextCode
82
+ if (nextStar !== -1 && nextStar < next) next = nextStar
83
+ if (next === text.length) {
84
+ result.push(text.substring(i))
85
+ break
86
+ }
87
+ result.push(text.substring(i, next))
88
+ i = next
89
+ }
90
+ }
91
+ return result.length > 0 ? result : text
92
+ }
2
93
 
3
94
  function Markdown(params, children) {
4
- if (typeof children === "string") {
5
- const lines = children
6
- .trim()
7
- .split("\n")
8
- .map((line) => line.trim())
9
- .filter(Boolean)
10
-
11
- return lines.map((line) => {
12
- if (line.startsWith("# ")) {
13
- const text = line.substring(2)
14
- return H1(params, text)
15
- } else if (line.startsWith("## ")) {
16
- const text = line.substring(3)
17
- return H2(params, text)
18
- } else if (line.startsWith("### ")) {
19
- const text = line.substring(4)
20
- return H3(params, text)
21
- } else if (line.startsWith("#### ")) {
22
- const text = line.substring(5)
23
- return H4(params, text)
24
- } else if (line.startsWith("##### ")) {
25
- const text = line.substring(6)
26
- return H5(params, text)
27
- } else if (line.startsWith("###### ")) {
28
- const text = line.substring(7)
29
- return H6(params, text)
30
- } else if (line.startsWith("> ")) {
31
- const text = line.substring(2)
32
- return Blockquote(params, text)
33
- }
34
-
35
- return P(params, line)
36
- })
37
- } else {
95
+ if (Array.isArray(children)) {
96
+ return children.map((child) => Markdown(params, child))
97
+ }
98
+
99
+ if (typeof children !== "string") {
38
100
  return null
39
101
  }
102
+
103
+ const lines = children
104
+ .trim()
105
+ .split("\n")
106
+ .map((line) => line.trim())
107
+ .filter(Boolean)
108
+
109
+ const items = lines
110
+ .map((line) => {
111
+ if (UNORDERED_MARKERS.some((marker) => line.startsWith(marker))) {
112
+ const content = line.substring(2)
113
+ if (!content) return null
114
+ return { type: "li", list: "ul", content }
115
+ }
116
+
117
+ if (ORDERED_LIST_REGEXP.test(line)) {
118
+ const content = line.replace(ORDERED_LIST_REGEXP, "")
119
+ if (!content) return null
120
+ return { type: "li", list: "ol", content }
121
+ }
122
+
123
+ for (const { prefix, type } of HEADINGS) {
124
+ if (line.startsWith(prefix)) {
125
+ return { type, content: line.substring(prefix.length) }
126
+ }
127
+ }
128
+
129
+ if (line.startsWith("> ")) {
130
+ return { type: "blockquote", content: line.substring(2) }
131
+ }
132
+
133
+ return { type: "p", content: line }
134
+ })
135
+ .filter(Boolean)
136
+
137
+ const nodes = []
138
+ let i = 0
139
+
140
+ while (i < items.length) {
141
+ const item = items[i]
142
+
143
+ if (item.type === "li") {
144
+ const list = []
145
+ const parent = item.list
146
+
147
+ while (
148
+ i < items.length &&
149
+ items[i].type === "li" &&
150
+ items[i].list === parent
151
+ ) {
152
+ list.push(Li(params, format(items[i].content)))
153
+ i++
154
+ }
155
+
156
+ if (parent === "ul") {
157
+ nodes.push(Ul(params, list))
158
+ } else if (parent === "ol") {
159
+ nodes.push(Ol(params, list))
160
+ }
161
+ } else if (item.type === "blockquote") {
162
+ const lines = []
163
+
164
+ while (i < items.length && items[i].type === "blockquote") {
165
+ lines.push(items[i].content)
166
+ i++
167
+ }
168
+
169
+ nodes.push(Blockquote(params, P(params, format(lines.join("\n")))))
170
+ } else {
171
+ const { type, content } = item
172
+ const Component = COMPONENTS[type] || P
173
+ nodes.push(Component(params, format(content)))
174
+ i++
175
+ }
176
+ }
177
+
178
+ return nodes
40
179
  }
41
180
 
42
181
  module.exports = component(Markdown)