@sakura-ui/sakura-ui 0.2.0 → 0.3.0

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 (215) hide show
  1. package/README.md +16 -6
  2. package/package.json +21 -15
  3. package/packages/core/package.json +26 -15
  4. package/packages/core/src/components/Button.tsx +33 -32
  5. package/packages/core/src/components/Card.tsx +29 -17
  6. package/packages/core/src/components/Code.tsx +6 -4
  7. package/packages/core/src/components/Faq.tsx +13 -7
  8. package/packages/core/src/components/Heading.tsx +42 -32
  9. package/packages/core/src/components/Icon.tsx +43 -13
  10. package/packages/core/src/components/IconButton.tsx +54 -43
  11. package/packages/core/src/components/LangSelector.tsx +135 -0
  12. package/packages/core/src/components/Link.tsx +38 -66
  13. package/packages/core/src/components/LinkCard.tsx +91 -0
  14. package/packages/core/src/components/List.tsx +14 -12
  15. package/packages/core/src/components/MenuButton.tsx +112 -0
  16. package/packages/core/src/components/NavigationItem.tsx +41 -0
  17. package/packages/core/src/components/OverflowContainer.tsx +24 -0
  18. package/packages/core/src/components/PopoverMenu.tsx +81 -0
  19. package/packages/core/src/components/Pre.tsx +6 -4
  20. package/packages/core/src/components/Table.tsx +31 -25
  21. package/packages/core/src/components/buttonStyle.ts +42 -31
  22. package/packages/core/src/components/index.ts +13 -25
  23. package/packages/core/src/icons/Close.tsx +21 -0
  24. package/packages/core/src/icons/CloseMobile.tsx +43 -0
  25. package/packages/core/src/icons/KeyboardArrowDown.tsx +24 -0
  26. package/packages/core/src/icons/Language.tsx +25 -0
  27. package/packages/core/src/icons/LanguageMobile.tsx +40 -0
  28. package/packages/core/src/icons/Menu.tsx +24 -0
  29. package/packages/core/src/icons/MenuMobile.tsx +40 -0
  30. package/packages/core/src/icons/index.ts +8 -0
  31. package/packages/core/src/icons/props.ts +5 -0
  32. package/packages/core/src/index.ts +9 -28
  33. package/packages/core/src/type.d.ts +1 -0
  34. package/packages/core/tests/Button.test.tsx +20 -10
  35. package/packages/core/tests/Card.test.tsx +16 -11
  36. package/packages/core/tests/IconButton.test.tsx +57 -0
  37. package/packages/core/tests/Link.test.tsx +60 -0
  38. package/packages/core/tests/vitest.setup.ts +1 -0
  39. package/packages/core/tsconfig.node.json +3 -2
  40. package/packages/forms/.turbo/turbo-build.log +22 -0
  41. package/packages/forms/dist/index.cjs.js +199 -120
  42. package/packages/forms/dist/index.es.js +890 -1023
  43. package/packages/forms/dist/types/components/Checkbox.d.ts +9 -4
  44. package/packages/forms/dist/types/components/Checkbox.d.ts.map +1 -1
  45. package/packages/forms/dist/types/components/FieldsetControl.d.ts +14 -9
  46. package/packages/forms/dist/types/components/FieldsetControl.d.ts.map +1 -1
  47. package/packages/forms/dist/types/components/FileInput.d.ts +10 -3
  48. package/packages/forms/dist/types/components/FileInput.d.ts.map +1 -1
  49. package/packages/forms/dist/types/components/Input.d.ts +9 -4
  50. package/packages/forms/dist/types/components/Input.d.ts.map +1 -1
  51. package/packages/forms/dist/types/components/LabelControl.d.ts +13 -8
  52. package/packages/forms/dist/types/components/LabelControl.d.ts.map +1 -1
  53. package/packages/forms/dist/types/components/Radio.d.ts +9 -4
  54. package/packages/forms/dist/types/components/Radio.d.ts.map +1 -1
  55. package/packages/forms/dist/types/components/Select.d.ts +9 -4
  56. package/packages/forms/dist/types/components/Select.d.ts.map +1 -1
  57. package/packages/forms/dist/types/components/Textarea.d.ts +8 -3
  58. package/packages/forms/dist/types/components/Textarea.d.ts.map +1 -1
  59. package/packages/forms/dist/types/components/controlled/CheckboxGroup.d.ts +16 -11
  60. package/packages/forms/dist/types/components/controlled/CheckboxGroup.d.ts.map +1 -1
  61. package/packages/forms/dist/types/components/controlled/RadioGroup.d.ts +17 -12
  62. package/packages/forms/dist/types/components/controlled/RadioGroup.d.ts.map +1 -1
  63. package/packages/forms/dist/types/components/index.d.ts +8 -8
  64. package/packages/forms/dist/types/components/index.d.ts.map +1 -1
  65. package/packages/forms/dist/types/components/inputStyle.d.ts +1 -1
  66. package/packages/forms/dist/types/components/inputStyle.d.ts.map +1 -1
  67. package/packages/forms/dist/types/index.d.ts +0 -1
  68. package/packages/forms/dist/types/index.d.ts.map +1 -1
  69. package/packages/forms/node_modules/.bin/autoprefixer +2 -2
  70. package/packages/forms/node_modules/.bin/tailwind +2 -2
  71. package/packages/forms/node_modules/.bin/tailwindcss +2 -2
  72. package/packages/forms/node_modules/.bin/ts-node +4 -4
  73. package/packages/forms/node_modules/.bin/ts-node-cwd +4 -4
  74. package/packages/forms/node_modules/.bin/ts-node-esm +4 -4
  75. package/packages/forms/node_modules/.bin/ts-node-script +4 -4
  76. package/packages/forms/node_modules/.bin/ts-node-transpile-only +4 -4
  77. package/packages/forms/node_modules/.bin/ts-script +4 -4
  78. package/packages/forms/node_modules/.bin/tsc +17 -0
  79. package/packages/forms/node_modules/.bin/tsserver +17 -0
  80. package/packages/forms/node_modules/.vite/vitest/results.json +1 -0
  81. package/packages/forms/package.json +17 -14
  82. package/packages/forms/src/components/Checkbox.tsx +76 -80
  83. package/packages/forms/src/components/FieldsetControl.tsx +21 -28
  84. package/packages/forms/src/components/FileInput.tsx +87 -63
  85. package/packages/forms/src/components/Input.tsx +29 -31
  86. package/packages/forms/src/components/LabelControl.tsx +19 -25
  87. package/packages/forms/src/components/Radio.tsx +66 -69
  88. package/packages/forms/src/components/Select.tsx +65 -65
  89. package/packages/forms/src/components/Textarea.tsx +49 -54
  90. package/packages/forms/src/components/controlled/CheckboxGroup.tsx +15 -17
  91. package/packages/forms/src/components/controlled/RadioGroup.tsx +16 -18
  92. package/packages/forms/src/components/index.ts +8 -8
  93. package/packages/forms/src/components/inputStyle.ts +7 -8
  94. package/packages/forms/src/index.ts +0 -11
  95. package/packages/forms/tests/Checkbox.test.tsx +44 -0
  96. package/packages/forms/tests/FieldsetControl.test.tsx +62 -11
  97. package/packages/forms/tests/FileInput.test.tsx +25 -0
  98. package/packages/forms/tests/Input.test.tsx +12 -83
  99. package/packages/forms/tests/LabelControl.test.tsx +82 -20
  100. package/packages/forms/tests/Radio.test.tsx +23 -78
  101. package/packages/forms/tests/Select.test.tsx +30 -0
  102. package/packages/forms/tests/Textarea.test.tsx +25 -0
  103. package/packages/forms/tests/vitest.setup.ts +1 -0
  104. package/packages/forms/tsconfig.node.json +3 -2
  105. package/packages/helper/.turbo/turbo-build.log +23 -0
  106. package/packages/helper/dist/index.cjs.js +78 -0
  107. package/packages/helper/dist/index.es.js +119 -0
  108. package/packages/helper/dist/types/calc.d.ts +2 -0
  109. package/packages/helper/dist/types/calc.d.ts.map +1 -0
  110. package/packages/{forms/dist/types/utils/class.d.ts → helper/dist/types/cx.d.ts} +1 -1
  111. package/packages/helper/dist/types/cx.d.ts.map +1 -0
  112. package/packages/helper/dist/types/index.d.ts +6 -0
  113. package/packages/helper/dist/types/index.d.ts.map +1 -0
  114. package/packages/helper/dist/types/querySelector.d.ts +2 -0
  115. package/packages/helper/dist/types/querySelector.d.ts.map +1 -0
  116. package/packages/helper/dist/types/styles.d.ts +22 -0
  117. package/packages/helper/dist/types/styles.d.ts.map +1 -0
  118. package/packages/helper/dist/types/treefy.d.ts +8 -0
  119. package/packages/helper/dist/types/treefy.d.ts.map +1 -0
  120. package/packages/helper/package.json +40 -0
  121. package/packages/helper/src/calc.ts +1 -0
  122. package/packages/helper/src/index.ts +5 -0
  123. package/packages/helper/src/querySelector.ts +20 -0
  124. package/packages/helper/src/styles.ts +116 -0
  125. package/packages/helper/src/treefy.ts +22 -0
  126. package/packages/helper/tsconfig.json +13 -0
  127. package/packages/helper/tsconfig.node.json +6 -0
  128. package/packages/helper/vite.config.ts +26 -0
  129. package/packages/markdown/.turbo/turbo-build.log +22 -0
  130. package/packages/markdown/README.md +129 -0
  131. package/packages/markdown/dist/index.cjs.js +175 -0
  132. package/packages/markdown/dist/index.es.js +17098 -0
  133. package/packages/markdown/dist/types/components/Markdown.d.ts +15 -0
  134. package/packages/markdown/dist/types/components/Markdown.d.ts.map +1 -0
  135. package/packages/markdown/dist/types/components/index.d.ts +2 -0
  136. package/packages/markdown/dist/types/components/index.d.ts.map +1 -0
  137. package/packages/markdown/dist/types/index.d.ts +2 -0
  138. package/packages/markdown/dist/types/index.d.ts.map +1 -0
  139. package/packages/markdown/dist/types/plugins/attr.d.ts +3 -0
  140. package/packages/markdown/dist/types/plugins/attr.d.ts.map +1 -0
  141. package/packages/markdown/dist/types/plugins/card.d.ts +3 -0
  142. package/packages/markdown/dist/types/plugins/card.d.ts.map +1 -0
  143. package/packages/markdown/dist/types/plugins/cell.d.ts +3 -0
  144. package/packages/markdown/dist/types/plugins/cell.d.ts.map +1 -0
  145. package/packages/markdown/dist/types/plugins/faq.d.ts +3 -0
  146. package/packages/markdown/dist/types/plugins/faq.d.ts.map +1 -0
  147. package/packages/markdown/dist/types/plugins/grid.d.ts +3 -0
  148. package/packages/markdown/dist/types/plugins/grid.d.ts.map +1 -0
  149. package/packages/markdown/dist/types/plugins/headings.d.ts +9 -0
  150. package/packages/markdown/dist/types/plugins/headings.d.ts.map +1 -0
  151. package/packages/markdown/dist/types/plugins/helper.d.ts +9 -0
  152. package/packages/markdown/dist/types/plugins/helper.d.ts.map +1 -0
  153. package/packages/markdown/dist/types/plugins/index.d.ts +9 -0
  154. package/packages/markdown/dist/types/plugins/index.d.ts.map +1 -0
  155. package/packages/markdown/dist/types/plugins/linkButton.d.ts +3 -0
  156. package/packages/markdown/dist/types/plugins/linkButton.d.ts.map +1 -0
  157. package/packages/markdown/dist/types/plugins/youtube.d.ts +3 -0
  158. package/packages/markdown/dist/types/plugins/youtube.d.ts.map +1 -0
  159. package/packages/markdown/node_modules/.bin/autoprefixer +17 -0
  160. package/packages/markdown/node_modules/.bin/tailwind +17 -0
  161. package/packages/markdown/node_modules/.bin/tailwindcss +17 -0
  162. package/packages/markdown/node_modules/.bin/ts-node +17 -0
  163. package/packages/markdown/node_modules/.bin/ts-node-cwd +17 -0
  164. package/packages/markdown/node_modules/.bin/ts-node-esm +17 -0
  165. package/packages/markdown/node_modules/.bin/ts-node-script +17 -0
  166. package/packages/markdown/node_modules/.bin/ts-node-transpile-only +17 -0
  167. package/packages/markdown/node_modules/.bin/ts-script +17 -0
  168. package/packages/markdown/node_modules/.bin/tsc +17 -0
  169. package/packages/markdown/node_modules/.bin/tsserver +17 -0
  170. package/packages/markdown/package.json +83 -0
  171. package/packages/markdown/src/components/Markdown.tsx +361 -0
  172. package/packages/markdown/src/components/index.ts +1 -0
  173. package/packages/markdown/src/global.d.ts +9 -0
  174. package/packages/markdown/src/index.ts +1 -0
  175. package/packages/markdown/src/plugins/attr.ts +19 -0
  176. package/packages/markdown/src/plugins/card.ts +57 -0
  177. package/packages/markdown/src/plugins/cell.ts +47 -0
  178. package/packages/markdown/src/plugins/faq.ts +40 -0
  179. package/packages/markdown/src/plugins/grid.ts +51 -0
  180. package/packages/markdown/src/plugins/headings.ts +35 -0
  181. package/packages/markdown/src/plugins/helper.ts +27 -0
  182. package/packages/markdown/src/plugins/index.ts +8 -0
  183. package/packages/markdown/src/plugins/linkButton.ts +25 -0
  184. package/packages/markdown/src/plugins/youtube.ts +48 -0
  185. package/packages/markdown/tsconfig.json +13 -0
  186. package/packages/markdown/tsconfig.node.json +7 -0
  187. package/packages/markdown/vite.config.ts +30 -0
  188. package/packages/tailwind-theme-plugin/.turbo/turbo-build.log +22 -0
  189. package/packages/tailwind-theme-plugin/dist/index.cjs.js +1 -1
  190. package/packages/tailwind-theme-plugin/dist/index.es.js +5354 -6111
  191. package/packages/tailwind-theme-plugin/dist/types/index.d.ts +1 -1
  192. package/packages/tailwind-theme-plugin/dist/types/index.d.ts.map +1 -1
  193. package/packages/tailwind-theme-plugin/node_modules/.bin/autoprefixer +2 -2
  194. package/packages/tailwind-theme-plugin/node_modules/.bin/tailwind +2 -2
  195. package/packages/tailwind-theme-plugin/node_modules/.bin/tailwindcss +2 -2
  196. package/packages/tailwind-theme-plugin/node_modules/.bin/ts-node +4 -4
  197. package/packages/tailwind-theme-plugin/node_modules/.bin/ts-node-cwd +4 -4
  198. package/packages/tailwind-theme-plugin/node_modules/.bin/ts-node-esm +4 -4
  199. package/packages/tailwind-theme-plugin/node_modules/.bin/ts-node-script +4 -4
  200. package/packages/tailwind-theme-plugin/node_modules/.bin/ts-node-transpile-only +4 -4
  201. package/packages/tailwind-theme-plugin/node_modules/.bin/ts-script +4 -4
  202. package/packages/tailwind-theme-plugin/node_modules/.bin/tsc +17 -0
  203. package/packages/tailwind-theme-plugin/node_modules/.bin/tsserver +17 -0
  204. package/packages/tailwind-theme-plugin/package.json +6 -6
  205. package/packages/tailwind-theme-plugin/src/index.ts +226 -291
  206. package/packages/core/src/libs/forward-ref.ts +0 -44
  207. package/packages/core/src/types/component.ts +0 -83
  208. package/packages/forms/dist/types/utils/class.d.ts.map +0 -1
  209. package/packages/forms/node_modules/.bin/acorn +0 -17
  210. package/packages/forms/node_modules/.bin/browserslist +0 -17
  211. package/packages/forms/node_modules/.bin/eslint +0 -17
  212. package/packages/forms/node_modules/.bin/vitest +0 -17
  213. package/packages/forms/src/utils/class.ts +0 -2
  214. package/packages/tailwind-theme-plugin/node_modules/.bin/browserslist +0 -17
  215. /package/packages/{core/src/libs → helper/src}/cx.ts +0 -0
@@ -0,0 +1,361 @@
1
+ import React, { Children } from 'react'
2
+ import * as production from 'react/jsx-runtime'
3
+ import { remark } from 'remark'
4
+ import { unified } from 'unified'
5
+ import remarkParse from 'remark-parse'
6
+ import remarkGfm from 'remark-gfm'
7
+ import remarkDirective from 'remark-directive'
8
+ import remarkRehype from 'remark-rehype'
9
+ import remarkBreaks from 'remark-breaks'
10
+ import rehypeRaw from 'rehype-raw'
11
+ import rehypeExternalLinks from 'rehype-external-links'
12
+ import rebypeShiftHeding from 'rehype-shift-heading'
13
+ import rehypeReact from 'rehype-react'
14
+ import rehypeSlug from 'rehype-slug'
15
+ import { cx } from '@sakura-ui/helper'
16
+ import {
17
+ Link,
18
+ H1,
19
+ H2,
20
+ H3,
21
+ H4,
22
+ H5,
23
+ H6,
24
+ Table,
25
+ Caption,
26
+ Thead,
27
+ Tbody,
28
+ Th,
29
+ Tr,
30
+ Td,
31
+ Ul,
32
+ Ol,
33
+ Pre,
34
+ Code,
35
+ Faq,
36
+ Question,
37
+ Answer,
38
+ Button,
39
+ Card,
40
+ CardImg,
41
+ CardBody,
42
+ CardFooter,
43
+ LinkCard,
44
+ LinkCardHeader,
45
+ OverflowContainer
46
+ } from '@sakura-ui/core'
47
+ import {
48
+ attrPlugin,
49
+ youtubePlugin,
50
+ linkButtonPlugin,
51
+ gridPlugin,
52
+ cellPlugin,
53
+ cardPlugin,
54
+ faqPlugin,
55
+ headingsPlugin,
56
+ type HeadingItem
57
+ } from '../plugins'
58
+
59
+ interface TocProps {
60
+ items: HeadingItem[]
61
+ }
62
+
63
+ export const TableOfContents = ({ items }: TocProps) => {
64
+ return (
65
+ <>
66
+ {items.map((item) => {
67
+ return (
68
+ <li key={item.id}>
69
+ <Link href={`#${item.id}`}>{item.value}</Link>
70
+ {item.children ? (
71
+ <Ul>{<TableOfContents items={item.children} />}</Ul>
72
+ ) : null}
73
+ </li>
74
+ )
75
+ })}
76
+ </>
77
+ )
78
+ }
79
+
80
+ interface TableContainerProps extends React.ComponentPropsWithoutRef<'table'> {}
81
+
82
+ const TableContainer = (props: TableContainerProps) => {
83
+ const { className, children, ...restProps } = props
84
+
85
+ return (
86
+ <OverflowContainer>
87
+ <Table className={cx(className)} {...restProps}>
88
+ {children}
89
+ </Table>
90
+ </OverflowContainer>
91
+ )
92
+ }
93
+
94
+ interface DataProps {
95
+ [key: `data-${string}`]: unknown
96
+ }
97
+
98
+ interface AnchorProps extends React.ComponentPropsWithoutRef<'a'>, DataProps {}
99
+
100
+ const Anchor = (props: AnchorProps) => {
101
+ const { children, href, ...restProps } = props
102
+
103
+ if (restProps['data-node'] === 'link-button') {
104
+ return (
105
+ <Button as="a" variant="secondary" href={href}>
106
+ {children}
107
+ </Button>
108
+ )
109
+ }
110
+
111
+ return (
112
+ <Link href={href} {...restProps}>
113
+ {children}
114
+ </Link>
115
+ )
116
+ }
117
+
118
+ interface ArticleProps
119
+ extends React.ComponentPropsWithoutRef<'article'>,
120
+ DataProps {}
121
+
122
+ const Article = (props: ArticleProps) => {
123
+ const { children, className, ...restProps } = props
124
+
125
+ const node = restProps['data-node']
126
+
127
+ if (node === 'card') {
128
+ if (restProps['data-behavior'] === 'link') {
129
+ const href = restProps['data-href'] as string
130
+
131
+ return (
132
+ <LinkCard href={href} className={cx(className)}>
133
+ {children}
134
+ </LinkCard>
135
+ )
136
+ }
137
+ return <Card className={cx(className)}>{children}</Card>
138
+ }
139
+
140
+ return (
141
+ <article className={className} {...restProps}>
142
+ {children}
143
+ </article>
144
+ )
145
+ }
146
+
147
+ interface DivProps extends React.ComponentPropsWithoutRef<'div'>, DataProps {}
148
+
149
+ const Div = (props: DivProps) => {
150
+ const { children, ...restProps } = props
151
+
152
+ const node = restProps['data-node']
153
+
154
+ if (node === 'card-title') {
155
+ return <LinkCardHeader>{children}</LinkCardHeader>
156
+ }
157
+ if (node === 'card-description') {
158
+ return <CardBody>{children}</CardBody>
159
+ }
160
+ if (node === 'card-footer') {
161
+ return <CardFooter>{children}</CardFooter>
162
+ }
163
+
164
+ if (restProps['data-behavior'] === 'list') {
165
+ // Set the css class configured for cells to the ul tag
166
+ return (
167
+ <ul className={restProps.className}>
168
+ {Children.map(children, (child) => (
169
+ <li className="sm:grid" key={Math.random()}>
170
+ {child}
171
+ </li>
172
+ ))}
173
+ </ul>
174
+ )
175
+ }
176
+
177
+ return <div {...restProps}>{children}</div>
178
+ }
179
+
180
+ interface ImgProps extends React.ComponentPropsWithoutRef<'img'>, DataProps {}
181
+
182
+ const Img = (props: ImgProps) => {
183
+ const { children, className, ...restProps } = props
184
+
185
+ if (restProps['data-node'] === 'card-img') {
186
+ return (
187
+ <CardImg
188
+ className={cx('w-full aspect-[352/226]', className)}
189
+ {...restProps}
190
+ />
191
+ )
192
+ }
193
+
194
+ if (restProps['data-node'] === 'cell-img') {
195
+ return <img className={cx('mb-4', className)} {...restProps} />
196
+ }
197
+
198
+ return <img className={className} {...restProps} />
199
+ }
200
+
201
+ interface IframeProps extends React.ComponentPropsWithoutRef<'iframe'> {}
202
+
203
+ const Iframe = (props: IframeProps) => {
204
+ const { className, children, ...restProps } = props
205
+
206
+ const styleMargin = `
207
+ my-8
208
+ `
209
+
210
+ let style = `
211
+ aspect-video
212
+ w-full
213
+ max-w-[470px]
214
+ `
215
+
216
+ if (props.width || props.height) {
217
+ style = `
218
+ aspect-video
219
+ w-full
220
+ lg:aspect-auto
221
+ lg:w-[${props.width}px]
222
+ lg:h-[${props.height}px]
223
+ `
224
+ }
225
+
226
+ return (
227
+ <iframe className={cx(styleMargin, style, className)} {...restProps}>
228
+ {children}
229
+ </iframe>
230
+ )
231
+ }
232
+
233
+ const sleep = (time: number) =>
234
+ new Promise((resolve) => setTimeout(resolve, time))
235
+
236
+ type Props = {
237
+ tocTitle?: string
238
+ showToc?: boolean
239
+ shiftHeding?: number
240
+ children: string
241
+ }
242
+
243
+ export const Markdown = ({
244
+ children,
245
+ showToc,
246
+ tocTitle = '目次',
247
+ shiftHeding = 0
248
+ }: Props) => {
249
+ const [toc, setToc] = React.useState<HeadingItem[]>([])
250
+ const [element, setElement] = React.useState(<React.Fragment />)
251
+
252
+ const markdown2Headings = React.useCallback((md: string) => {
253
+ const result: any = remark().use(headingsPlugin).processSync(md)
254
+
255
+ const headings: HeadingItem[] = result.data.fm.headings.filter(
256
+ (obj: HeadingItem) => obj.depth < 3
257
+ )
258
+
259
+ return headings
260
+ }, [])
261
+
262
+ const markdown2ReactElements = React.useCallback(
263
+ (md: string) => {
264
+ const rhypeReactOptions = {
265
+ ...production,
266
+ components: {
267
+ a: Anchor,
268
+ article: Article,
269
+ button: Button,
270
+ code: Code,
271
+ dl: Faq,
272
+ dt: Question,
273
+ dd: Answer,
274
+ h1: H1,
275
+ h2: H2,
276
+ h3: H3,
277
+ h4: H4,
278
+ h5: H5,
279
+ h6: H6,
280
+ iframe: Iframe,
281
+ img: Img,
282
+ ul: Ul,
283
+ ol: Ol,
284
+ pre: Pre,
285
+ table: TableContainer,
286
+ caption: Caption,
287
+ thead: Thead,
288
+ tbody: Tbody,
289
+ th: Th,
290
+ tr: Tr,
291
+ td: Td,
292
+ div: Div
293
+ }
294
+ }
295
+
296
+ const elem = unified()
297
+ .use(remarkParse) // md -> mdast (Markdown Abstract Syntax Tree)
298
+ .use(remarkGfm) // mdast -> GFM mdast (GitHub Flavored Markdown Abstract Syntax Tree)
299
+ .use(remarkDirective) // support for directive syntax
300
+ .use(remarkBreaks)
301
+ .use(attrPlugin)
302
+ .use(youtubePlugin)
303
+ .use(linkButtonPlugin)
304
+ .use(cellPlugin)
305
+ .use(cardPlugin)
306
+ .use(faqPlugin)
307
+ .use(gridPlugin)
308
+ .use(remarkRehype, {
309
+ allowDangerousHtml: true
310
+ }) // mdast -> hast (HTML Abstract Syntax Tree)
311
+ .use(rehypeRaw) // hast -> hast
312
+ .use(rehypeExternalLinks, { target: '_blank' }) // hast -> hast
313
+ .use(rebypeShiftHeding, { shift: shiftHeding }) // hast -> hast
314
+ .use(rehypeSlug)
315
+ .use(rehypeReact, rhypeReactOptions as any) // hast -> React Elements
316
+ .processSync(md).result
317
+ return elem
318
+ },
319
+ [shiftHeding]
320
+ )
321
+
322
+ React.useEffect(() => {
323
+ setToc(markdown2Headings(children))
324
+ setElement(markdown2ReactElements(children))
325
+ }, [children, markdown2Headings, markdown2ReactElements])
326
+
327
+ React.useEffect(() => {
328
+ // Necessary to make in-page links work.
329
+ const scrollToHash = async () => {
330
+ await sleep(500)
331
+ if (location.hash) {
332
+ document
333
+ .getElementById(decodeURI(location.hash.substring(1)))
334
+ ?.scrollIntoView()
335
+ }
336
+ }
337
+ scrollToHash()
338
+ }, [])
339
+
340
+ const style = `
341
+ rounded-3xl
342
+ p-10
343
+ bg-yellow-50
344
+ `
345
+
346
+ return (
347
+ <div className="py-8 flex flex-col gap-8">
348
+ {showToc && (
349
+ <nav className={style}>
350
+ <h2 className="mb-4 font-bold text-h-xs-m sm:text-h-xs">
351
+ {tocTitle}
352
+ </h2>
353
+ <Ul>
354
+ <TableOfContents items={toc} />
355
+ </Ul>
356
+ </nav>
357
+ )}
358
+ {element}
359
+ </div>
360
+ )
361
+ }
@@ -0,0 +1 @@
1
+ export { Markdown } from './Markdown'
@@ -0,0 +1,9 @@
1
+ import type { JSX as Jsx } from 'react/jsx-runtime'
2
+
3
+ declare global {
4
+ namespace JSX {
5
+ type ElementClass = Jsx.ElementClass
6
+ type Element = Jsx.Element
7
+ type IntrinsicElements = Jsx.IntrinsicElements
8
+ }
9
+ }
@@ -0,0 +1 @@
1
+ export { Markdown } from './components'
@@ -0,0 +1,19 @@
1
+ import type { Root } from 'mdast'
2
+ import { h } from 'hastscript'
3
+ import { visit } from 'unist-util-visit'
4
+ import type { Directives } from 'mdast-util-directive'
5
+ import { isDirective } from './helper'
6
+
7
+ // This plugin is an example to turn `::node` into divs, passing arbitrary
8
+ // attributes.
9
+ export const attrPlugin = () => {
10
+ return (tree: Root) => {
11
+ visit(tree, isDirective, (node: Directives) => {
12
+ node.data = node.data ?? {}
13
+ const hast = h(node.name, node.attributes || {})
14
+
15
+ node.data.hName = hast.tagName
16
+ node.data.hProperties = hast.properties
17
+ })
18
+ }
19
+ }
@@ -0,0 +1,57 @@
1
+ import type { Root } from 'mdast'
2
+ import { h } from 'hastscript'
3
+ import { visit } from 'unist-util-visit'
4
+ import type { Directives } from 'mdast-util-directive'
5
+ import { isDirective } from './helper'
6
+
7
+ // This plugin is to turn `:::card` into divs, passing arbitrary
8
+ // attributes.
9
+ export const cardPlugin = () => {
10
+ return (tree: Root) => {
11
+ visit(tree, isDirective, (node: Directives) => {
12
+ if (node.type !== 'containerDirective') {
13
+ return
14
+ }
15
+ if (node.name !== 'card') {
16
+ return
17
+ }
18
+
19
+ node.data = node.data ?? {}
20
+
21
+ const tagName = 'article'
22
+
23
+ node.data.hName = tagName
24
+
25
+ node.attributes = node.attributes ?? {}
26
+ node.attributes['data-node'] = node.name
27
+
28
+ if (node.attributes.as === 'link') {
29
+ node.attributes.as = undefined
30
+ node.attributes['data-behavior'] = 'link'
31
+ node.attributes['data-href'] = node.attributes.href || ''
32
+ }
33
+
34
+ node.data.hProperties = h(tagName, node.attributes).properties
35
+
36
+ node.children.forEach((child) => {
37
+ if (!isDirective(child)) {
38
+ return
39
+ }
40
+
41
+ child.data = child.data ?? {}
42
+
43
+ let tagName = 'div'
44
+ if (child.name === 'card-img') {
45
+ tagName = 'img'
46
+ }
47
+
48
+ child.data.hName = tagName
49
+
50
+ child.attributes = child.attributes ?? {}
51
+ child.attributes['data-node'] = child.name
52
+
53
+ child.data.hProperties = h(tagName, child.attributes).properties
54
+ })
55
+ })
56
+ }
57
+ }
@@ -0,0 +1,47 @@
1
+ import type { Root } from 'mdast'
2
+ import { h } from 'hastscript'
3
+ import { visit } from 'unist-util-visit'
4
+ import type { Directives } from 'mdast-util-directive'
5
+ import { isContainerDirective, isDirective } from './helper'
6
+
7
+ // This plugin is to turn `:::cell` into divs, passing arbitrary
8
+ // attributes.
9
+ export const cellPlugin = () => {
10
+ return (tree: Root) => {
11
+ visit(tree, isContainerDirective, (node: Directives) => {
12
+ if (node.name !== 'cell') {
13
+ return
14
+ }
15
+
16
+ node.data = node.data ?? {}
17
+ const tagName = 'div'
18
+
19
+ node.data.hName = tagName
20
+
21
+ node.attributes = node.attributes ?? {}
22
+ node.attributes['data-node'] = node.name
23
+
24
+ node.data.hProperties = h(tagName, node.attributes).properties
25
+
26
+ node.children.forEach((child) => {
27
+ if (!isDirective(child)) {
28
+ return
29
+ }
30
+ if (child.name !== 'cell-img') {
31
+ return
32
+ }
33
+
34
+ child.data = child.data ?? {}
35
+
36
+ const tagName = 'img'
37
+
38
+ child.data.hName = tagName
39
+
40
+ child.attributes = child.attributes ?? {}
41
+ child.attributes['data-node'] = child.name
42
+
43
+ child.data.hProperties = h(tagName, child.attributes).properties
44
+ })
45
+ })
46
+ }
47
+ }
@@ -0,0 +1,40 @@
1
+ import type { Root } from 'mdast'
2
+ import { h } from 'hastscript'
3
+ import { visit } from 'unist-util-visit'
4
+ import type { Directives } from 'mdast-util-directive'
5
+ import { isContainerDirective, isDirective } from './helper'
6
+
7
+ // This plugin is to turn `::linkButton` into divs, passing arbitrary
8
+ // attributes.
9
+ export const faqPlugin = () => {
10
+ return (tree: Root) => {
11
+ visit(tree, isContainerDirective, (node: Directives) => {
12
+ if (node.name !== 'faq') {
13
+ return
14
+ }
15
+
16
+ node.data = node.data ?? {}
17
+ const tagName = 'dl'
18
+
19
+ node.data.hName = tagName
20
+
21
+ node.data.hProperties = h(tagName, node.attributes || {}).properties
22
+
23
+ node.children.forEach((child) => {
24
+ if (!isDirective(child)) {
25
+ return
26
+ }
27
+ if (child.name !== 'faq-q' && child.name !== 'faq-a') {
28
+ return
29
+ }
30
+
31
+ child.data = child.data ?? {}
32
+ const tagName = child.name === 'faq-q' ? 'dt' : 'dd'
33
+
34
+ child.data.hName = tagName
35
+
36
+ child.data.hProperties = h(tagName, child.attributes || {}).properties
37
+ })
38
+ })
39
+ }
40
+ }
@@ -0,0 +1,51 @@
1
+ import type { Root } from 'mdast'
2
+ import { h } from 'hastscript'
3
+ import { visit } from 'unist-util-visit'
4
+ import type { Directives } from 'mdast-util-directive'
5
+ import { isContainerDirective } from './helper'
6
+
7
+ // This plugin is to turn `::linkButton` into divs, passing arbitrary
8
+ // attributes.
9
+ export const gridPlugin = () => {
10
+ return (tree: Root) => {
11
+ visit(tree, isContainerDirective, (node: Directives) => {
12
+ if (!node.name.startsWith('grid-cols-')) {
13
+ return
14
+ }
15
+
16
+ node.attributes = node.attributes ?? {}
17
+
18
+ if (node.attributes.as === 'list') {
19
+ node.attributes.as = undefined
20
+ node.attributes['data-behavior'] = 'list'
21
+ }
22
+
23
+ const gridNum: number = Number.parseInt(node.name.split('-').pop() || '1')
24
+
25
+ // Tailwind doesn't generate CSS for string interpolation
26
+ const gridClass: { [key: number]: string } = {
27
+ 1: 'md:grid-cols-1',
28
+ 2: 'md:grid-cols-2',
29
+ 3: 'md:grid-cols-3',
30
+ 4: 'md:grid-cols-4',
31
+ 5: 'md:grid-cols-5',
32
+ 6: 'md:grid-cols-6',
33
+ 7: 'md:grid-cols-6',
34
+ 8: 'md:grid-cols-6',
35
+ 9: 'md:grid-cols-6',
36
+ 10: 'md:grid-cols-6',
37
+ 11: 'md:grid-cols-6',
38
+ 12: 'md:grid-cols-12'
39
+ }
40
+
41
+ node.data = node.data ?? {}
42
+ const tagName = 'div'
43
+
44
+ node.data.hName = tagName
45
+
46
+ node.attributes.class = `flex flex-col md:grid ${gridClass[gridNum]} gap-8`
47
+
48
+ node.data.hProperties = h(tagName, node.attributes).properties
49
+ })
50
+ }
51
+ }
@@ -0,0 +1,35 @@
1
+ import type { Heading, Root } from 'mdast'
2
+ import Slugger from 'github-slugger'
3
+ import { visit } from 'unist-util-visit'
4
+ import { toString as mdastToString } from 'mdast-util-to-string'
5
+ import { treefy } from '@sakura-ui/helper'
6
+ import { isHeading } from './helper'
7
+
8
+ export type HeadingItem = {
9
+ id?: string
10
+ depth: number
11
+ value?: string
12
+ children?: Array<HeadingItem>
13
+ }
14
+
15
+ export const headingsPlugin = () => {
16
+ return (tree: Root, vFile: any) => {
17
+ const headings: Array<HeadingItem> = []
18
+ const slugger = new Slugger()
19
+
20
+ const getFlatHeadingsList = (node: Heading) => {
21
+ const h: HeadingItem = {
22
+ id: slugger.slug(mdastToString(node)),
23
+ depth: node.depth,
24
+ value: mdastToString(node)
25
+ }
26
+
27
+ headings.push(h)
28
+ }
29
+
30
+ visit(tree, isHeading, getFlatHeadingsList)
31
+
32
+ if (!vFile.data.fm) vFile.data.fm = {}
33
+ vFile.data.fm.headings = treefy(headings)
34
+ }
35
+ }
@@ -0,0 +1,27 @@
1
+ import type { Directives } from 'mdast-util-directive'
2
+ import type { Node } from 'unist'
3
+ import type { Heading } from 'mdast'
4
+
5
+ export const isDirective = (node: Node): node is Directives => {
6
+ return (
7
+ node.type === 'containerDirective' ||
8
+ node.type === 'leafDirective' ||
9
+ node.type === 'textDirective'
10
+ )
11
+ }
12
+
13
+ export const isContainerDirective = (node: Node): node is Directives => {
14
+ return node.type === 'containerDirective'
15
+ }
16
+
17
+ export const isLeafDirective = (node: Node): node is Directives => {
18
+ return node.type === 'leafDirective'
19
+ }
20
+
21
+ export const isTextDirective = (node: Node): node is Directives => {
22
+ return node.type === 'textDirective'
23
+ }
24
+
25
+ export const isHeading = (node: Node): node is Heading => {
26
+ return node.type === 'heading'
27
+ }
@@ -0,0 +1,8 @@
1
+ export { youtubePlugin } from './youtube'
2
+ export { attrPlugin } from './attr'
3
+ export { linkButtonPlugin } from './linkButton'
4
+ export { gridPlugin } from './grid'
5
+ export { cellPlugin } from './cell'
6
+ export { cardPlugin } from './card'
7
+ export { faqPlugin } from './faq'
8
+ export { headingsPlugin, type HeadingItem } from './headings'
@@ -0,0 +1,25 @@
1
+ import type { Root } from 'mdast'
2
+ import { h } from 'hastscript'
3
+ import { visit } from 'unist-util-visit'
4
+ import type { Directives } from 'mdast-util-directive'
5
+ import { isTextDirective } from './helper'
6
+
7
+ // This plugin is to turn `::linkButton` into divs, passing arbitrary
8
+ // attributes.
9
+ export const linkButtonPlugin = () => {
10
+ return (tree: Root) => {
11
+ visit(tree, isTextDirective, (node: Directives) => {
12
+ if (node.name !== 'link-button') return
13
+
14
+ const data = node.data || (node.data = {})
15
+ const tagName = 'a'
16
+
17
+ data.hName = tagName
18
+
19
+ node.attributes = node.attributes ?? {}
20
+ node.attributes['data-node'] = node.name
21
+
22
+ data.hProperties = h(tagName, node.attributes).properties
23
+ })
24
+ }
25
+ }