pd-markdown 1.0.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 (235) hide show
  1. package/package.json +26 -0
  2. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/index.d.ts +4 -0
  3. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/index.d.ts.map +1 -0
  4. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/index.js +5 -0
  5. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/index.js.map +1 -0
  6. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/index.d.ts +4 -0
  7. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/index.d.ts.map +1 -0
  8. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/index.js +4 -0
  9. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/index.js.map +1 -0
  10. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/transform/heading.d.ts +6 -0
  11. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/transform/heading.d.ts.map +1 -0
  12. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/transform/heading.js +36 -0
  13. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/transform/heading.js.map +1 -0
  14. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/transform/list.d.ts +14 -0
  15. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/transform/list.d.ts.map +1 -0
  16. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/transform/list.js +18 -0
  17. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/transform/list.js.map +1 -0
  18. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/transform/table.d.ts +27 -0
  19. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/transform/table.d.ts.map +1 -0
  20. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/transform/table.js +37 -0
  21. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/plugins/transform/table.js.map +1 -0
  22. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/processor.d.ts +22 -0
  23. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/processor.d.ts.map +1 -0
  24. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/processor.js +95 -0
  25. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/processor.js.map +1 -0
  26. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/types/index.d.ts +55 -0
  27. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/types/index.d.ts.map +1 -0
  28. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/types/index.js +2 -0
  29. package/packages/parser/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/parser/dist/types/index.js.map +1 -0
  30. package/packages/parser/__tests__/frontmatter.test.ts +69 -0
  31. package/packages/parser/__tests__/gfm.test.ts +83 -0
  32. package/packages/parser/__tests__/processor.test.ts +136 -0
  33. package/packages/parser/__tests__/transform/heading.test.ts +56 -0
  34. package/packages/parser/__tests__/transform/list.test.ts +67 -0
  35. package/packages/parser/__tests__/transform/table.test.ts +85 -0
  36. package/packages/parser/dist/index.cjs +191 -0
  37. package/packages/parser/dist/index.cjs.map +1 -0
  38. package/packages/parser/dist/index.d.ts +4 -0
  39. package/packages/parser/dist/index.d.ts.map +1 -0
  40. package/packages/parser/dist/index.mjs +185 -0
  41. package/packages/parser/dist/index.mjs.map +1 -0
  42. package/packages/parser/dist/plugins/index.d.ts +4 -0
  43. package/packages/parser/dist/plugins/index.d.ts.map +1 -0
  44. package/packages/parser/dist/plugins/transform/heading.d.ts +6 -0
  45. package/packages/parser/dist/plugins/transform/heading.d.ts.map +1 -0
  46. package/packages/parser/dist/plugins/transform/list.d.ts +14 -0
  47. package/packages/parser/dist/plugins/transform/list.d.ts.map +1 -0
  48. package/packages/parser/dist/plugins/transform/table.d.ts +27 -0
  49. package/packages/parser/dist/plugins/transform/table.d.ts.map +1 -0
  50. package/packages/parser/dist/processor.d.ts +22 -0
  51. package/packages/parser/dist/processor.d.ts.map +1 -0
  52. package/packages/parser/dist/types/index.d.ts +55 -0
  53. package/packages/parser/dist/types/index.d.ts.map +1 -0
  54. package/packages/parser/node_modules/.bin/yaml +17 -0
  55. package/packages/parser/package.json +38 -0
  56. package/packages/parser/rollup.config.ts +38 -0
  57. package/packages/parser/src/index.ts +15 -0
  58. package/packages/parser/src/plugins/index.ts +3 -0
  59. package/packages/parser/src/plugins/transform/heading.ts +40 -0
  60. package/packages/parser/src/plugins/transform/list.ts +29 -0
  61. package/packages/parser/src/plugins/transform/table.ts +62 -0
  62. package/packages/parser/src/processor.ts +119 -0
  63. package/packages/parser/src/types/index.ts +60 -0
  64. package/packages/parser/tsconfig.json +9 -0
  65. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/ast/query.d.ts +36 -0
  66. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/ast/query.d.ts.map +1 -0
  67. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/ast/query.js +99 -0
  68. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/ast/query.js.map +1 -0
  69. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/ast/traverse.d.ts +22 -0
  70. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/ast/traverse.d.ts.map +1 -0
  71. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/ast/traverse.js +46 -0
  72. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/ast/traverse.js.map +1 -0
  73. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/index.d.ts +7 -0
  74. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/index.d.ts.map +1 -0
  75. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/index.js +8 -0
  76. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/index.js.map +1 -0
  77. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/string/sanitize.d.ts +22 -0
  78. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/string/sanitize.d.ts.map +1 -0
  79. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/string/sanitize.js +140 -0
  80. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/string/sanitize.js.map +1 -0
  81. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/string/slugify.d.ts +16 -0
  82. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/string/slugify.d.ts.map +1 -0
  83. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/string/slugify.js +39 -0
  84. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/string/slugify.js.map +1 -0
  85. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/types/index.d.ts +49 -0
  86. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/types/index.d.ts.map +1 -0
  87. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/types/index.js +19 -0
  88. package/packages/utils/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/utils/dist/types/index.js.map +1 -0
  89. package/packages/utils/__tests__/query.test.ts +155 -0
  90. package/packages/utils/__tests__/sanitize.test.ts +96 -0
  91. package/packages/utils/__tests__/slugify.test.ts +71 -0
  92. package/packages/utils/__tests__/traverse.test.ts +131 -0
  93. package/packages/utils/dist/ast/query.d.ts +36 -0
  94. package/packages/utils/dist/ast/query.d.ts.map +1 -0
  95. package/packages/utils/dist/ast/traverse.d.ts +22 -0
  96. package/packages/utils/dist/ast/traverse.d.ts.map +1 -0
  97. package/packages/utils/dist/index.cjs +358 -0
  98. package/packages/utils/dist/index.cjs.map +1 -0
  99. package/packages/utils/dist/index.d.ts +7 -0
  100. package/packages/utils/dist/index.d.ts.map +1 -0
  101. package/packages/utils/dist/index.mjs +343 -0
  102. package/packages/utils/dist/index.mjs.map +1 -0
  103. package/packages/utils/dist/string/sanitize.d.ts +22 -0
  104. package/packages/utils/dist/string/sanitize.d.ts.map +1 -0
  105. package/packages/utils/dist/string/slugify.d.ts +16 -0
  106. package/packages/utils/dist/string/slugify.d.ts.map +1 -0
  107. package/packages/utils/dist/types/index.d.ts +49 -0
  108. package/packages/utils/dist/types/index.d.ts.map +1 -0
  109. package/packages/utils/package.json +27 -0
  110. package/packages/utils/rollup.config.ts +26 -0
  111. package/packages/utils/src/ast/query.ts +127 -0
  112. package/packages/utils/src/ast/traverse.ts +73 -0
  113. package/packages/utils/src/index.ts +20 -0
  114. package/packages/utils/src/string/sanitize.ts +155 -0
  115. package/packages/utils/src/string/slugify.ts +43 -0
  116. package/packages/utils/src/types/index.ts +72 -0
  117. package/packages/utils/tsconfig.json +8 -0
  118. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/MarkdownRenderer.d.ts +27 -0
  119. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/MarkdownRenderer.d.ts.map +1 -0
  120. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/MarkdownRenderer.js +39 -0
  121. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/MarkdownRenderer.js.map +1 -0
  122. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/NodeRenderer.d.ts +10 -0
  123. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/NodeRenderer.d.ts.map +1 -0
  124. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/NodeRenderer.js +130 -0
  125. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/NodeRenderer.js.map +1 -0
  126. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/context.d.ts +17 -0
  127. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/context.d.ts.map +1 -0
  128. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/context.js +14 -0
  129. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/context.js.map +1 -0
  130. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Blockquote.d.ts +8 -0
  131. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Blockquote.d.ts.map +1 -0
  132. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Blockquote.js +5 -0
  133. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Blockquote.js.map +1 -0
  134. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Code.d.ts +13 -0
  135. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Code.d.ts.map +1 -0
  136. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Code.js +9 -0
  137. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Code.js.map +1 -0
  138. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Heading.d.ts +8 -0
  139. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Heading.d.ts.map +1 -0
  140. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Heading.js +7 -0
  141. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Heading.js.map +1 -0
  142. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Image.d.ts +7 -0
  143. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Image.d.ts.map +1 -0
  144. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Image.js +5 -0
  145. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Image.js.map +1 -0
  146. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Link.d.ts +8 -0
  147. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Link.d.ts.map +1 -0
  148. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Link.js +7 -0
  149. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Link.js.map +1 -0
  150. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/List.d.ts +13 -0
  151. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/List.d.ts.map +1 -0
  152. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/List.js +14 -0
  153. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/List.js.map +1 -0
  154. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Paragraph.d.ts +8 -0
  155. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Paragraph.d.ts.map +1 -0
  156. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Paragraph.js +5 -0
  157. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Paragraph.js.map +1 -0
  158. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Table.d.ts +19 -0
  159. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Table.d.ts.map +1 -0
  160. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Table.js +18 -0
  161. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/Table.js.map +1 -0
  162. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/index.d.ts +34 -0
  163. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/index.d.ts.map +1 -0
  164. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/index.js +28 -0
  165. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/components/defaults/index.js.map +1 -0
  166. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/hooks/useMarkdown.d.ts +11 -0
  167. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/hooks/useMarkdown.d.ts.map +1 -0
  168. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/hooks/useMarkdown.js +28 -0
  169. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/hooks/useMarkdown.js.map +1 -0
  170. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/index.d.ts +6 -0
  171. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/index.d.ts.map +1 -0
  172. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/index.js +9 -0
  173. package/packages/web/.rollup.cache/Users/pidan/Work/Learn/pd-markdown/packages/web/dist/index.js.map +1 -0
  174. package/packages/web/__tests__/MarkdownRenderer.test.tsx +89 -0
  175. package/packages/web/__tests__/NodeRenderer.test.tsx +97 -0
  176. package/packages/web/__tests__/components/Code.test.tsx +71 -0
  177. package/packages/web/__tests__/components/Heading.test.tsx +65 -0
  178. package/packages/web/__tests__/components/List.test.tsx +100 -0
  179. package/packages/web/__tests__/components/Table.test.tsx +105 -0
  180. package/packages/web/__tests__/useMarkdown.test.ts +63 -0
  181. package/packages/web/dist/components/MarkdownRenderer.d.ts +27 -0
  182. package/packages/web/dist/components/MarkdownRenderer.d.ts.map +1 -0
  183. package/packages/web/dist/components/NodeRenderer.d.ts +10 -0
  184. package/packages/web/dist/components/NodeRenderer.d.ts.map +1 -0
  185. package/packages/web/dist/components/context.d.ts +17 -0
  186. package/packages/web/dist/components/context.d.ts.map +1 -0
  187. package/packages/web/dist/components/defaults/Blockquote.d.ts +8 -0
  188. package/packages/web/dist/components/defaults/Blockquote.d.ts.map +1 -0
  189. package/packages/web/dist/components/defaults/Code.d.ts +13 -0
  190. package/packages/web/dist/components/defaults/Code.d.ts.map +1 -0
  191. package/packages/web/dist/components/defaults/Heading.d.ts +8 -0
  192. package/packages/web/dist/components/defaults/Heading.d.ts.map +1 -0
  193. package/packages/web/dist/components/defaults/Image.d.ts +7 -0
  194. package/packages/web/dist/components/defaults/Image.d.ts.map +1 -0
  195. package/packages/web/dist/components/defaults/Link.d.ts +8 -0
  196. package/packages/web/dist/components/defaults/Link.d.ts.map +1 -0
  197. package/packages/web/dist/components/defaults/List.d.ts +13 -0
  198. package/packages/web/dist/components/defaults/List.d.ts.map +1 -0
  199. package/packages/web/dist/components/defaults/Paragraph.d.ts +8 -0
  200. package/packages/web/dist/components/defaults/Paragraph.d.ts.map +1 -0
  201. package/packages/web/dist/components/defaults/Table.d.ts +19 -0
  202. package/packages/web/dist/components/defaults/Table.d.ts.map +1 -0
  203. package/packages/web/dist/components/defaults/index.d.ts +34 -0
  204. package/packages/web/dist/components/defaults/index.d.ts.map +1 -0
  205. package/packages/web/dist/hooks/useMarkdown.d.ts +11 -0
  206. package/packages/web/dist/hooks/useMarkdown.d.ts.map +1 -0
  207. package/packages/web/dist/index.cjs +306 -0
  208. package/packages/web/dist/index.cjs.map +1 -0
  209. package/packages/web/dist/index.d.ts +6 -0
  210. package/packages/web/dist/index.d.ts.map +1 -0
  211. package/packages/web/dist/index.mjs +287 -0
  212. package/packages/web/dist/index.mjs.map +1 -0
  213. package/packages/web/package.json +40 -0
  214. package/packages/web/rollup.config.ts +36 -0
  215. package/packages/web/src/components/MarkdownRenderer.tsx +70 -0
  216. package/packages/web/src/components/NodeRenderer.tsx +205 -0
  217. package/packages/web/src/components/context.ts +24 -0
  218. package/packages/web/src/components/defaults/Blockquote.tsx +11 -0
  219. package/packages/web/src/components/defaults/Code.tsx +26 -0
  220. package/packages/web/src/components/defaults/Heading.tsx +14 -0
  221. package/packages/web/src/components/defaults/Image.tsx +10 -0
  222. package/packages/web/src/components/defaults/Link.tsx +18 -0
  223. package/packages/web/src/components/defaults/List.tsx +33 -0
  224. package/packages/web/src/components/defaults/Paragraph.tsx +11 -0
  225. package/packages/web/src/components/defaults/Table.tsx +50 -0
  226. package/packages/web/src/components/defaults/index.tsx +80 -0
  227. package/packages/web/src/hooks/useMarkdown.ts +32 -0
  228. package/packages/web/src/index.ts +37 -0
  229. package/packages/web/tsconfig.json +11 -0
  230. package/packages/web/vitest.config.ts +9 -0
  231. package/pnpm-workspace.yaml +2 -0
  232. package/tsconfig.base.json +26 -0
  233. package/tsconfig.json +8 -0
  234. package/vitest.config.ts +28 -0
  235. package/vitest.setup.ts +1 -0
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Convert text to URL-safe slug
3
+ *
4
+ * @param text - Text to slugify
5
+ * @returns URL-safe slug
6
+ */
7
+ export function slugify(text) {
8
+ return (text
9
+ // Convert to lowercase
10
+ .toLowerCase()
11
+ // Replace Chinese characters with pinyin-like representation (keep as-is for simplicity)
12
+ // Replace spaces and special chars with hyphens
13
+ .replace(/[\s_]+/g, '-')
14
+ // Remove characters that aren't alphanumeric, hyphens, or common CJK
15
+ .replace(/[^\w\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff-]/g, '')
16
+ // Replace multiple consecutive hyphens with single hyphen
17
+ .replace(/-+/g, '-')
18
+ // Remove leading/trailing hyphens
19
+ .replace(/^-+|-+$/g, ''));
20
+ }
21
+ /**
22
+ * Generate unique slug with counter suffix for duplicates
23
+ *
24
+ * @param text - Text to slugify
25
+ * @param existingSlugs - Set of existing slugs to check against
26
+ * @returns Unique slug
27
+ */
28
+ export function uniqueSlugify(text, existingSlugs) {
29
+ const baseSlug = slugify(text);
30
+ let slug = baseSlug;
31
+ let counter = 1;
32
+ while (existingSlugs.has(slug)) {
33
+ slug = `${baseSlug}-${counter}`;
34
+ counter++;
35
+ }
36
+ existingSlugs.add(slug);
37
+ return slug;
38
+ }
39
+ //# sourceMappingURL=slugify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slugify.js","sourceRoot":"","sources":["../../src/string/slugify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,CACL,IAAI;QACF,uBAAuB;SACtB,WAAW,EAAE;QACd,yFAAyF;QACzF,gDAAgD;SAC/C,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;QACxB,qEAAqE;SACpE,OAAO,CAAC,gDAAgD,EAAE,EAAE,CAAC;QAC9D,0DAA0D;SACzD,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;QACpB,kCAAkC;SACjC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAC3B,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,aAA0B;IACpE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B,IAAI,IAAI,GAAG,QAAQ,CAAA;IACnB,IAAI,OAAO,GAAG,CAAC,CAAA;IAEf,OAAO,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,IAAI,GAAG,GAAG,QAAQ,IAAI,OAAO,EAAE,CAAA;QAC/B,OAAO,EAAE,CAAA;IACX,CAAC;IAED,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACvB,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,49 @@
1
+ import type { Root, Content, Parent, Literal } from 'mdast';
2
+ import type { Node as UnistNode } from 'unist';
3
+ export type { Root, Content, Parent, Literal };
4
+ /**
5
+ * All possible markdown node types
6
+ */
7
+ export type MdNode = Root | Content;
8
+ /**
9
+ * Root node of markdown AST
10
+ */
11
+ export type MdRoot = Root;
12
+ /**
13
+ * Visitor function for AST traversal
14
+ */
15
+ export type Visitor<T extends UnistNode = MdNode> = (node: T, index: number | undefined, parent: Parent | undefined) => void | boolean;
16
+ /**
17
+ * Plugin options base interface
18
+ */
19
+ export interface PluginOptions {
20
+ [key: string]: unknown;
21
+ }
22
+ /**
23
+ * Position information in source
24
+ */
25
+ export interface Position {
26
+ line: number;
27
+ column: number;
28
+ offset?: number;
29
+ }
30
+ /**
31
+ * Location in source
32
+ */
33
+ export interface Location {
34
+ start: Position;
35
+ end: Position;
36
+ }
37
+ /**
38
+ * Type guard to check if node is a parent node
39
+ */
40
+ export declare function isParent(node: UnistNode): node is Parent;
41
+ /**
42
+ * Type guard to check if node is a literal node
43
+ */
44
+ export declare function isLiteral(node: UnistNode): node is Literal;
45
+ /**
46
+ * Type guard to check if node has specific type
47
+ */
48
+ export declare function isNodeType<T extends MdNode>(node: UnistNode, type: T['type']): node is T;
49
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC3D,OAAO,KAAK,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,OAAO,CAAA;AAG9C,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;AAE9C;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,OAAO,CAAA;AAEnC;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,IAAI,CAAA;AAEzB;;GAEG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,SAAS,GAAG,MAAM,IAAI,CAClD,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,EAAE,MAAM,GAAG,SAAS,KACvB,IAAI,GAAG,OAAO,CAAA;AAEnB;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,QAAQ,CAAA;IACf,GAAG,EAAE,QAAQ,CAAA;CACd;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,IAAI,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,IAAI,OAAO,CAE1D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EACzC,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,GACd,IAAI,IAAI,CAAC,CAEX"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Type guard to check if node is a parent node
3
+ */
4
+ export function isParent(node) {
5
+ return 'children' in node && Array.isArray(node.children);
6
+ }
7
+ /**
8
+ * Type guard to check if node is a literal node
9
+ */
10
+ export function isLiteral(node) {
11
+ return 'value' in node && typeof node.value === 'string';
12
+ }
13
+ /**
14
+ * Type guard to check if node has specific type
15
+ */
16
+ export function isNodeType(node, type) {
17
+ return node.type === type;
18
+ }
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAiDA;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAe;IACtC,OAAO,UAAU,IAAI,IAAI,IAAI,KAAK,CAAC,OAAO,CAAE,IAAe,CAAC,QAAQ,CAAC,CAAA;AACvE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAe;IACvC,OAAO,OAAO,IAAI,IAAI,IAAI,OAAQ,IAAgB,CAAC,KAAK,KAAK,QAAQ,CAAA;AACvE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CACxB,IAAe,EACf,IAAe;IAEf,OAAO,IAAI,CAAC,IAAI,KAAK,IAAI,CAAA;AAC3B,CAAC"}
@@ -0,0 +1,155 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { findNodes, findNode, findNodesBy, findParent } from '../src/ast/query'
3
+ import type { Root, Paragraph, Text, Heading, Strong } from 'mdast'
4
+
5
+ describe('findNodes', () => {
6
+ const createAst = (): Root => ({
7
+ type: 'root',
8
+ children: [
9
+ {
10
+ type: 'heading',
11
+ depth: 1,
12
+ children: [{ type: 'text', value: 'Title' }],
13
+ } as Heading,
14
+ {
15
+ type: 'paragraph',
16
+ children: [
17
+ { type: 'text', value: 'Hello ' },
18
+ {
19
+ type: 'strong',
20
+ children: [{ type: 'text', value: 'world' }],
21
+ } as Strong,
22
+ ],
23
+ } as Paragraph,
24
+ {
25
+ type: 'heading',
26
+ depth: 2,
27
+ children: [{ type: 'text', value: 'Subtitle' }],
28
+ } as Heading,
29
+ ],
30
+ })
31
+
32
+ it('should find all nodes of specified type', () => {
33
+ const ast = createAst()
34
+ const headings = findNodes<Heading>(ast, 'heading')
35
+
36
+ expect(headings).toHaveLength(2)
37
+ expect(headings[0].depth).toBe(1)
38
+ expect(headings[1].depth).toBe(2)
39
+ })
40
+
41
+ it('should find nested nodes', () => {
42
+ const ast = createAst()
43
+ const texts = findNodes<Text>(ast, 'text')
44
+
45
+ expect(texts).toHaveLength(4)
46
+ expect(texts.map((t) => t.value)).toEqual([
47
+ 'Title',
48
+ 'Hello ',
49
+ 'world',
50
+ 'Subtitle',
51
+ ])
52
+ })
53
+
54
+ it('should return empty array when no matches', () => {
55
+ const ast = createAst()
56
+ const codes = findNodes(ast, 'code')
57
+
58
+ expect(codes).toEqual([])
59
+ })
60
+ })
61
+
62
+ describe('findNode', () => {
63
+ const createAst = (): Root => ({
64
+ type: 'root',
65
+ children: [
66
+ {
67
+ type: 'heading',
68
+ depth: 1,
69
+ children: [{ type: 'text', value: 'First' }],
70
+ } as Heading,
71
+ {
72
+ type: 'heading',
73
+ depth: 2,
74
+ children: [{ type: 'text', value: 'Second' }],
75
+ } as Heading,
76
+ ],
77
+ })
78
+
79
+ it('should find first matching node', () => {
80
+ const ast = createAst()
81
+ const heading = findNode<Heading>(ast, 'heading')
82
+
83
+ expect(heading).toBeDefined()
84
+ expect(heading!.depth).toBe(1)
85
+ })
86
+
87
+ it('should return undefined when no match', () => {
88
+ const ast = createAst()
89
+ const code = findNode(ast, 'code')
90
+
91
+ expect(code).toBeUndefined()
92
+ })
93
+ })
94
+
95
+ describe('findNodesBy', () => {
96
+ const createAst = (): Root => ({
97
+ type: 'root',
98
+ children: [
99
+ {
100
+ type: 'heading',
101
+ depth: 1,
102
+ children: [{ type: 'text', value: 'H1' }],
103
+ } as Heading,
104
+ {
105
+ type: 'heading',
106
+ depth: 2,
107
+ children: [{ type: 'text', value: 'H2' }],
108
+ } as Heading,
109
+ {
110
+ type: 'heading',
111
+ depth: 1,
112
+ children: [{ type: 'text', value: 'Another H1' }],
113
+ } as Heading,
114
+ ],
115
+ })
116
+
117
+ it('should find nodes matching predicate', () => {
118
+ const ast = createAst()
119
+ const h1s = findNodesBy<Heading>(
120
+ ast,
121
+ (node) => node.type === 'heading' && (node as Heading).depth === 1
122
+ )
123
+
124
+ expect(h1s).toHaveLength(2)
125
+ expect(h1s[0].children[0]).toHaveProperty('value', 'H1')
126
+ expect(h1s[1].children[0]).toHaveProperty('value', 'Another H1')
127
+ })
128
+ })
129
+
130
+ describe('findParent', () => {
131
+ it('should find parent of a node', () => {
132
+ const textNode: Text = { type: 'text', value: 'Hello' }
133
+ const paragraph: Paragraph = {
134
+ type: 'paragraph',
135
+ children: [textNode],
136
+ }
137
+ const ast: Root = {
138
+ type: 'root',
139
+ children: [paragraph],
140
+ }
141
+
142
+ const parent = findParent(ast, textNode)
143
+ expect(parent).toBe(paragraph)
144
+ })
145
+
146
+ it('should return undefined for root node', () => {
147
+ const ast: Root = {
148
+ type: 'root',
149
+ children: [],
150
+ }
151
+
152
+ const parent = findParent(ast, ast)
153
+ expect(parent).toBeUndefined()
154
+ })
155
+ })
@@ -0,0 +1,96 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { escapeHtml, sanitizeHtml, stripHtml } from '../src/string/sanitize'
3
+
4
+ describe('escapeHtml', () => {
5
+ it('should escape ampersand', () => {
6
+ expect(escapeHtml('foo & bar')).toBe('foo &amp; bar')
7
+ })
8
+
9
+ it('should escape less than', () => {
10
+ expect(escapeHtml('a < b')).toBe('a &lt; b')
11
+ })
12
+
13
+ it('should escape greater than', () => {
14
+ expect(escapeHtml('a > b')).toBe('a &gt; b')
15
+ })
16
+
17
+ it('should escape double quotes', () => {
18
+ expect(escapeHtml('say "hello"')).toBe('say &quot;hello&quot;')
19
+ })
20
+
21
+ it('should escape single quotes', () => {
22
+ expect(escapeHtml("it's")).toBe('it&#39;s')
23
+ })
24
+
25
+ it('should escape multiple characters', () => {
26
+ expect(escapeHtml('<script>alert("xss")</script>')).toBe(
27
+ '&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;'
28
+ )
29
+ })
30
+
31
+ it('should preserve safe text', () => {
32
+ expect(escapeHtml('Hello World 123')).toBe('Hello World 123')
33
+ })
34
+ })
35
+
36
+ describe('sanitizeHtml', () => {
37
+ it('should remove script tags', () => {
38
+ expect(sanitizeHtml('<script>alert("xss")</script>')).toBe('')
39
+ })
40
+
41
+ it('should remove event handlers', () => {
42
+ expect(sanitizeHtml('<div onclick="alert(1)">text</div>')).toBe(
43
+ '<div>text</div>'
44
+ )
45
+ })
46
+
47
+ it('should remove javascript: URLs', () => {
48
+ expect(sanitizeHtml('<a href="javascript:alert(1)">click</a>')).toBe(
49
+ '<a href="">click</a>'
50
+ )
51
+ })
52
+
53
+ it('should preserve allowed tags', () => {
54
+ expect(sanitizeHtml('<p>Hello <strong>world</strong></p>')).toBe(
55
+ '<p>Hello <strong>world</strong></p>'
56
+ )
57
+ })
58
+
59
+ it('should preserve allowed attributes', () => {
60
+ expect(sanitizeHtml('<a href="https://example.com" title="link">text</a>')).toBe(
61
+ '<a href="https://example.com" title="link">text</a>'
62
+ )
63
+ })
64
+
65
+ it('should remove disallowed tags', () => {
66
+ expect(sanitizeHtml('<iframe src="evil.com"></iframe>')).toBe('')
67
+ })
68
+
69
+ it('should remove disallowed attributes', () => {
70
+ expect(sanitizeHtml('<div data-evil="bad">text</div>')).toBe('<div>text</div>')
71
+ })
72
+
73
+ it('should handle nested script content', () => {
74
+ expect(
75
+ sanitizeHtml('<div><script>bad()</script>safe</div>')
76
+ ).toBe('<div>safe</div>')
77
+ })
78
+ })
79
+
80
+ describe('stripHtml', () => {
81
+ it('should remove all HTML tags', () => {
82
+ expect(stripHtml('<p>Hello <strong>world</strong></p>')).toBe('Hello world')
83
+ })
84
+
85
+ it('should handle self-closing tags', () => {
86
+ expect(stripHtml('Hello<br/>World')).toBe('HelloWorld')
87
+ })
88
+
89
+ it('should preserve text content', () => {
90
+ expect(stripHtml('No tags here')).toBe('No tags here')
91
+ })
92
+
93
+ it('should handle nested tags', () => {
94
+ expect(stripHtml('<div><p><span>Deep</span></p></div>')).toBe('Deep')
95
+ })
96
+ })
@@ -0,0 +1,71 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { slugify, uniqueSlugify } from '../src/string/slugify'
3
+
4
+ describe('slugify', () => {
5
+ it('should convert text to lowercase', () => {
6
+ expect(slugify('Hello World')).toBe('hello-world')
7
+ })
8
+
9
+ it('should replace spaces with hyphens', () => {
10
+ expect(slugify('hello world')).toBe('hello-world')
11
+ })
12
+
13
+ it('should replace underscores with hyphens', () => {
14
+ expect(slugify('hello_world')).toBe('hello-world')
15
+ })
16
+
17
+ it('should remove special characters', () => {
18
+ expect(slugify('Hello! World?')).toBe('hello-world')
19
+ })
20
+
21
+ it('should handle multiple consecutive spaces', () => {
22
+ expect(slugify('hello world')).toBe('hello-world')
23
+ })
24
+
25
+ it('should remove leading and trailing hyphens', () => {
26
+ expect(slugify(' hello world ')).toBe('hello-world')
27
+ })
28
+
29
+ it('should preserve Chinese characters', () => {
30
+ expect(slugify('你好世界')).toBe('你好世界')
31
+ })
32
+
33
+ it('should handle mixed Chinese and English', () => {
34
+ expect(slugify('Hello 你好 World')).toBe('hello-你好-world')
35
+ })
36
+
37
+ it('should handle Japanese characters', () => {
38
+ expect(slugify('こんにちは')).toBe('こんにちは')
39
+ })
40
+
41
+ it('should return empty string for only special characters', () => {
42
+ expect(slugify('!@#$%')).toBe('')
43
+ })
44
+
45
+ it('should handle numbers', () => {
46
+ expect(slugify('Chapter 1')).toBe('chapter-1')
47
+ })
48
+ })
49
+
50
+ describe('uniqueSlugify', () => {
51
+ it('should return base slug when no duplicates', () => {
52
+ const existing = new Set<string>()
53
+ expect(uniqueSlugify('Hello World', existing)).toBe('hello-world')
54
+ })
55
+
56
+ it('should add counter for duplicates', () => {
57
+ const existing = new Set(['hello-world'])
58
+ expect(uniqueSlugify('Hello World', existing)).toBe('hello-world-1')
59
+ })
60
+
61
+ it('should increment counter for multiple duplicates', () => {
62
+ const existing = new Set(['hello-world', 'hello-world-1', 'hello-world-2'])
63
+ expect(uniqueSlugify('Hello World', existing)).toBe('hello-world-3')
64
+ })
65
+
66
+ it('should add generated slug to existing set', () => {
67
+ const existing = new Set<string>()
68
+ uniqueSlugify('Hello World', existing)
69
+ expect(existing.has('hello-world')).toBe(true)
70
+ })
71
+ })
@@ -0,0 +1,131 @@
1
+ import { describe, it, expect, vi } from 'vitest'
2
+ import { traverseAst, traverseAstWithCallbacks } from '../src/ast/traverse'
3
+ import type { Root, Paragraph, Text, Heading } from 'mdast'
4
+
5
+ describe('traverseAst', () => {
6
+ const createSimpleAst = (): Root => ({
7
+ type: 'root',
8
+ children: [
9
+ {
10
+ type: 'heading',
11
+ depth: 1,
12
+ children: [{ type: 'text', value: 'Title' }],
13
+ } as Heading,
14
+ {
15
+ type: 'paragraph',
16
+ children: [{ type: 'text', value: 'Content' }],
17
+ } as Paragraph,
18
+ ],
19
+ })
20
+
21
+ it('should visit all nodes in depth-first order', () => {
22
+ const ast = createSimpleAst()
23
+ const visited: string[] = []
24
+
25
+ traverseAst(ast, (node) => {
26
+ visited.push(node.type)
27
+ })
28
+
29
+ expect(visited).toEqual(['root', 'heading', 'text', 'paragraph', 'text'])
30
+ })
31
+
32
+ it('should skip children when visitor returns false', () => {
33
+ const ast = createSimpleAst()
34
+ const visited: string[] = []
35
+
36
+ traverseAst(ast, (node) => {
37
+ visited.push(node.type)
38
+ if (node.type === 'heading') {
39
+ return false // Skip children of heading
40
+ }
41
+ })
42
+
43
+ expect(visited).toEqual(['root', 'heading', 'paragraph', 'text'])
44
+ })
45
+
46
+ it('should provide correct index and parent', () => {
47
+ const ast = createSimpleAst()
48
+ const visitor = vi.fn()
49
+
50
+ traverseAst(ast, visitor)
51
+
52
+ // Root has no index and no parent
53
+ expect(visitor).toHaveBeenNthCalledWith(1, ast, undefined, undefined)
54
+
55
+ // Heading is at index 0 with root as parent
56
+ expect(visitor).toHaveBeenNthCalledWith(2, ast.children[0], 0, ast)
57
+ })
58
+
59
+ it('should handle empty children', () => {
60
+ const ast: Root = {
61
+ type: 'root',
62
+ children: [],
63
+ }
64
+ const visited: string[] = []
65
+
66
+ traverseAst(ast, (node) => {
67
+ visited.push(node.type)
68
+ })
69
+
70
+ expect(visited).toEqual(['root'])
71
+ })
72
+ })
73
+
74
+ describe('traverseAstWithCallbacks', () => {
75
+ const createSimpleAst = (): Root => ({
76
+ type: 'root',
77
+ children: [
78
+ {
79
+ type: 'paragraph',
80
+ children: [{ type: 'text', value: 'Hello' }],
81
+ } as Paragraph,
82
+ ],
83
+ })
84
+
85
+ it('should call enter and leave in correct order', () => {
86
+ const ast = createSimpleAst()
87
+ const events: string[] = []
88
+
89
+ traverseAstWithCallbacks(ast, {
90
+ enter: (node) => {
91
+ events.push(`enter:${node.type}`)
92
+ },
93
+ leave: (node) => {
94
+ events.push(`leave:${node.type}`)
95
+ },
96
+ })
97
+
98
+ expect(events).toEqual([
99
+ 'enter:root',
100
+ 'enter:paragraph',
101
+ 'enter:text',
102
+ 'leave:text',
103
+ 'leave:paragraph',
104
+ 'leave:root',
105
+ ])
106
+ })
107
+
108
+ it('should skip children when enter returns false', () => {
109
+ const ast = createSimpleAst()
110
+ const events: string[] = []
111
+
112
+ traverseAstWithCallbacks(ast, {
113
+ enter: (node) => {
114
+ events.push(`enter:${node.type}`)
115
+ if (node.type === 'paragraph') {
116
+ return false
117
+ }
118
+ },
119
+ leave: (node) => {
120
+ events.push(`leave:${node.type}`)
121
+ },
122
+ })
123
+
124
+ expect(events).toEqual([
125
+ 'enter:root',
126
+ 'enter:paragraph',
127
+ 'leave:paragraph',
128
+ 'leave:root',
129
+ ])
130
+ })
131
+ })
@@ -0,0 +1,36 @@
1
+ import type { Node } from 'unist';
2
+ import type { MdNode, Parent } from '../types';
3
+ /**
4
+ * Find all nodes of a specific type in the AST
5
+ *
6
+ * @param node - Root node to search from
7
+ * @param type - Node type to find
8
+ * @returns Array of matching nodes
9
+ */
10
+ export declare function findNodes<T extends Node = MdNode>(node: Node, type: string): T[];
11
+ /**
12
+ * Find the first node of a specific type in the AST
13
+ *
14
+ * @param node - Root node to search from
15
+ * @param type - Node type to find
16
+ * @returns The first matching node or undefined
17
+ */
18
+ export declare function findNode<T extends Node = MdNode>(node: Node, type: string): T | undefined;
19
+ /**
20
+ * Find all nodes matching a predicate
21
+ *
22
+ * @param node - Root node to search from
23
+ * @param predicate - Function to test each node
24
+ * @returns Array of matching nodes
25
+ */
26
+ export declare function findNodesBy<T extends Node = MdNode>(node: Node, predicate: (node: Node) => boolean): T[];
27
+ /**
28
+ * Get the parent of a node in the AST
29
+ * Note: This requires traversing from root, use sparingly
30
+ *
31
+ * @param root - Root node of the AST
32
+ * @param target - Node to find parent of
33
+ * @returns Parent node or undefined if not found or is root
34
+ */
35
+ export declare function findParent(root: Node, target: Node): Parent | undefined;
36
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/ast/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAG9C;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,IAAI,GAAG,MAAM,EAC/C,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,MAAM,GACX,CAAC,EAAE,CAiBL;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,IAAI,GAAG,MAAM,EAC9C,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,MAAM,GACX,CAAC,GAAG,SAAS,CAsBf;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,IAAI,GAAG,MAAM,EACjD,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,GACjC,CAAC,EAAE,CAiBL;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAsBvE"}
@@ -0,0 +1,22 @@
1
+ import type { Node } from 'unist';
2
+ import type { MdNode, Visitor } from '../types';
3
+ /**
4
+ * Traverse AST in depth-first order
5
+ *
6
+ * @param node - Root node to start traversal
7
+ * @param visitor - Visitor function called for each node
8
+ * Return `false` to skip children of current node
9
+ * Return `true` or `undefined` to continue
10
+ */
11
+ export declare function traverseAst<T extends Node = MdNode>(node: T, visitor: Visitor<T>): void;
12
+ /**
13
+ * Traverse AST with enter and leave callbacks
14
+ *
15
+ * @param node - Root node to start traversal
16
+ * @param callbacks - Object with optional enter and leave functions
17
+ */
18
+ export declare function traverseAstWithCallbacks<T extends Node = MdNode>(node: T, callbacks: {
19
+ enter?: Visitor<T>;
20
+ leave?: Visitor<T>;
21
+ }): void;
22
+ //# sourceMappingURL=traverse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traverse.d.ts","sourceRoot":"","sources":["../../src/ast/traverse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,KAAK,EAAU,MAAM,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAGvD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,IAAI,GAAG,MAAM,EACjD,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAClB,IAAI,CAsBN;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,IAAI,GAAG,MAAM,EAC9D,IAAI,EAAE,CAAC,EACP,SAAS,EAAE;IACT,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;CACnB,GACA,IAAI,CAqBN"}