@knpkv/confluence-to-markdown 0.2.0 → 0.4.1

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 (336) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/LICENSE +21 -0
  3. package/README.md +282 -14
  4. package/dist/ConfluenceAuth.d.ts +76 -0
  5. package/dist/ConfluenceAuth.d.ts.map +1 -0
  6. package/dist/ConfluenceAuth.js +356 -0
  7. package/dist/ConfluenceAuth.js.map +1 -0
  8. package/dist/ConfluenceClient.d.ts +26 -2
  9. package/dist/ConfluenceClient.d.ts.map +1 -1
  10. package/dist/ConfluenceClient.js +98 -92
  11. package/dist/ConfluenceClient.js.map +1 -1
  12. package/dist/ConfluenceConfig.d.ts +4 -24
  13. package/dist/ConfluenceConfig.d.ts.map +1 -1
  14. package/dist/ConfluenceConfig.js +45 -7
  15. package/dist/ConfluenceConfig.js.map +1 -1
  16. package/dist/ConfluenceError.d.ts +89 -6
  17. package/dist/ConfluenceError.d.ts.map +1 -1
  18. package/dist/ConfluenceError.js +88 -5
  19. package/dist/ConfluenceError.js.map +1 -1
  20. package/dist/GitError.d.ts +103 -0
  21. package/dist/GitError.d.ts.map +1 -0
  22. package/dist/GitError.js +85 -0
  23. package/dist/GitError.js.map +1 -0
  24. package/dist/GitService.d.ts +175 -0
  25. package/dist/GitService.d.ts.map +1 -0
  26. package/dist/GitService.js +431 -0
  27. package/dist/GitService.js.map +1 -0
  28. package/dist/LocalFileSystem.d.ts +29 -4
  29. package/dist/LocalFileSystem.d.ts.map +1 -1
  30. package/dist/LocalFileSystem.js +80 -6
  31. package/dist/LocalFileSystem.js.map +1 -1
  32. package/dist/MarkdownConverter.d.ts +49 -2
  33. package/dist/MarkdownConverter.d.ts.map +1 -1
  34. package/dist/MarkdownConverter.js +73 -111
  35. package/dist/MarkdownConverter.js.map +1 -1
  36. package/dist/SchemaConverterError.d.ts +108 -0
  37. package/dist/SchemaConverterError.d.ts.map +1 -0
  38. package/dist/SchemaConverterError.js +84 -0
  39. package/dist/SchemaConverterError.js.map +1 -0
  40. package/dist/Schemas.d.ts +225 -1
  41. package/dist/Schemas.d.ts.map +1 -1
  42. package/dist/Schemas.js +155 -6
  43. package/dist/Schemas.js.map +1 -1
  44. package/dist/SyncEngine.d.ts +30 -20
  45. package/dist/SyncEngine.d.ts.map +1 -1
  46. package/dist/SyncEngine.js +566 -117
  47. package/dist/SyncEngine.js.map +1 -1
  48. package/dist/ast/BlockNode.d.ts +468 -0
  49. package/dist/ast/BlockNode.d.ts.map +1 -0
  50. package/dist/ast/BlockNode.js +319 -0
  51. package/dist/ast/BlockNode.js.map +1 -0
  52. package/dist/ast/Document.d.ts +244 -0
  53. package/dist/ast/Document.d.ts.map +1 -0
  54. package/dist/ast/Document.js +69 -0
  55. package/dist/ast/Document.js.map +1 -0
  56. package/dist/ast/InlineNode.d.ts +477 -0
  57. package/dist/ast/InlineNode.d.ts.map +1 -0
  58. package/dist/ast/InlineNode.js +263 -0
  59. package/dist/ast/InlineNode.js.map +1 -0
  60. package/dist/ast/MacroNode.d.ts +267 -0
  61. package/dist/ast/MacroNode.d.ts.map +1 -0
  62. package/dist/ast/MacroNode.js +164 -0
  63. package/dist/ast/MacroNode.js.map +1 -0
  64. package/dist/ast/index.d.ts +10 -0
  65. package/dist/ast/index.d.ts.map +1 -0
  66. package/dist/ast/index.js +14 -0
  67. package/dist/ast/index.js.map +1 -0
  68. package/dist/bin.js +33 -149
  69. package/dist/bin.js.map +1 -1
  70. package/dist/commands/auth.d.ts +15 -0
  71. package/dist/commands/auth.d.ts.map +1 -0
  72. package/dist/commands/auth.js +86 -0
  73. package/dist/commands/auth.js.map +1 -0
  74. package/dist/commands/clone.d.ts +12 -0
  75. package/dist/commands/clone.d.ts.map +1 -0
  76. package/dist/commands/clone.js +93 -0
  77. package/dist/commands/clone.js.map +1 -0
  78. package/dist/commands/delete.d.ts +13 -0
  79. package/dist/commands/delete.d.ts.map +1 -0
  80. package/dist/commands/delete.js +48 -0
  81. package/dist/commands/delete.js.map +1 -0
  82. package/dist/commands/errorHandler.d.ts +14 -0
  83. package/dist/commands/errorHandler.d.ts.map +1 -0
  84. package/dist/commands/errorHandler.js +33 -0
  85. package/dist/commands/errorHandler.js.map +1 -0
  86. package/dist/commands/git.d.ts +22 -0
  87. package/dist/commands/git.d.ts.map +1 -0
  88. package/dist/commands/git.js +72 -0
  89. package/dist/commands/git.js.map +1 -0
  90. package/dist/commands/index.d.ts +11 -0
  91. package/dist/commands/index.d.ts.map +1 -0
  92. package/dist/commands/index.js +11 -0
  93. package/dist/commands/index.js.map +1 -0
  94. package/dist/commands/layers.d.ts +31 -0
  95. package/dist/commands/layers.d.ts.map +1 -0
  96. package/dist/commands/layers.js +137 -0
  97. package/dist/commands/layers.js.map +1 -0
  98. package/dist/commands/new.d.ts +9 -0
  99. package/dist/commands/new.d.ts.map +1 -0
  100. package/dist/commands/new.js +80 -0
  101. package/dist/commands/new.js.map +1 -0
  102. package/dist/commands/pageTree.d.ts +18 -0
  103. package/dist/commands/pageTree.d.ts.map +1 -0
  104. package/dist/commands/pageTree.js +20 -0
  105. package/dist/commands/pageTree.js.map +1 -0
  106. package/dist/commands/shared.d.ts +15 -0
  107. package/dist/commands/shared.d.ts.map +1 -0
  108. package/dist/commands/shared.js +27 -0
  109. package/dist/commands/shared.js.map +1 -0
  110. package/dist/commands/sync.d.ts +15 -0
  111. package/dist/commands/sync.d.ts.map +1 -0
  112. package/dist/commands/sync.js +101 -0
  113. package/dist/commands/sync.js.map +1 -0
  114. package/dist/index.d.ts +10 -1
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js +14 -0
  117. package/dist/index.js.map +1 -1
  118. package/dist/internal/NodeLayers.d.ts +7 -0
  119. package/dist/internal/NodeLayers.d.ts.map +1 -0
  120. package/dist/internal/NodeLayers.js +19 -0
  121. package/dist/internal/NodeLayers.js.map +1 -0
  122. package/dist/internal/frontmatter.d.ts +10 -0
  123. package/dist/internal/frontmatter.d.ts.map +1 -1
  124. package/dist/internal/frontmatter.js +16 -0
  125. package/dist/internal/frontmatter.js.map +1 -1
  126. package/dist/internal/gitCommands.d.ts +78 -0
  127. package/dist/internal/gitCommands.d.ts.map +1 -0
  128. package/dist/internal/gitCommands.js +156 -0
  129. package/dist/internal/gitCommands.js.map +1 -0
  130. package/dist/internal/hashUtils.d.ts +42 -1
  131. package/dist/internal/hashUtils.d.ts.map +1 -1
  132. package/dist/internal/hashUtils.js +38 -2
  133. package/dist/internal/hashUtils.js.map +1 -1
  134. package/dist/internal/oauthServer.d.ts +55 -0
  135. package/dist/internal/oauthServer.d.ts.map +1 -0
  136. package/dist/internal/oauthServer.js +110 -0
  137. package/dist/internal/oauthServer.js.map +1 -0
  138. package/dist/internal/pathUtils.d.ts +21 -4
  139. package/dist/internal/pathUtils.d.ts.map +1 -1
  140. package/dist/internal/pathUtils.js +24 -13
  141. package/dist/internal/pathUtils.js.map +1 -1
  142. package/dist/internal/tokenStorage.d.ts +75 -0
  143. package/dist/internal/tokenStorage.d.ts.map +1 -0
  144. package/dist/internal/tokenStorage.js +149 -0
  145. package/dist/internal/tokenStorage.js.map +1 -0
  146. package/dist/internal/userCache.d.ts +42 -0
  147. package/dist/internal/userCache.d.ts.map +1 -0
  148. package/dist/internal/userCache.js +51 -0
  149. package/dist/internal/userCache.js.map +1 -0
  150. package/dist/parsers/ConfluenceParser.d.ts +26 -0
  151. package/dist/parsers/ConfluenceParser.d.ts.map +1 -0
  152. package/dist/parsers/ConfluenceParser.js +792 -0
  153. package/dist/parsers/ConfluenceParser.js.map +1 -0
  154. package/dist/parsers/MarkdownParser.d.ts +26 -0
  155. package/dist/parsers/MarkdownParser.d.ts.map +1 -0
  156. package/dist/parsers/MarkdownParser.js +873 -0
  157. package/dist/parsers/MarkdownParser.js.map +1 -0
  158. package/dist/parsers/index.d.ts +8 -0
  159. package/dist/parsers/index.d.ts.map +1 -0
  160. package/dist/parsers/index.js +8 -0
  161. package/dist/parsers/index.js.map +1 -0
  162. package/dist/schemas/ConfluenceSchema.d.ts +21 -0
  163. package/dist/schemas/ConfluenceSchema.d.ts.map +1 -0
  164. package/dist/schemas/ConfluenceSchema.js +38 -0
  165. package/dist/schemas/ConfluenceSchema.js.map +1 -0
  166. package/dist/schemas/ConversionSchema.d.ts +35 -0
  167. package/dist/schemas/ConversionSchema.d.ts.map +1 -0
  168. package/dist/schemas/ConversionSchema.js +208 -0
  169. package/dist/schemas/ConversionSchema.js.map +1 -0
  170. package/dist/schemas/MarkdownSchema.d.ts +21 -0
  171. package/dist/schemas/MarkdownSchema.d.ts.map +1 -0
  172. package/dist/schemas/MarkdownSchema.js +38 -0
  173. package/dist/schemas/MarkdownSchema.js.map +1 -0
  174. package/dist/schemas/hast/HastFromHtml.d.ts +27 -0
  175. package/dist/schemas/hast/HastFromHtml.d.ts.map +1 -0
  176. package/dist/schemas/hast/HastFromHtml.js +107 -0
  177. package/dist/schemas/hast/HastFromHtml.js.map +1 -0
  178. package/dist/schemas/hast/HastSchema.d.ts +195 -0
  179. package/dist/schemas/hast/HastSchema.d.ts.map +1 -0
  180. package/dist/schemas/hast/HastSchema.js +183 -0
  181. package/dist/schemas/hast/HastSchema.js.map +1 -0
  182. package/dist/schemas/hast/index.d.ts +9 -0
  183. package/dist/schemas/hast/index.d.ts.map +1 -0
  184. package/dist/schemas/hast/index.js +3 -0
  185. package/dist/schemas/hast/index.js.map +1 -0
  186. package/dist/schemas/index.d.ts +14 -0
  187. package/dist/schemas/index.d.ts.map +1 -0
  188. package/dist/schemas/index.js +16 -0
  189. package/dist/schemas/index.js.map +1 -0
  190. package/dist/schemas/mdast/MdastFromMarkdown.d.ts +30 -0
  191. package/dist/schemas/mdast/MdastFromMarkdown.d.ts.map +1 -0
  192. package/dist/schemas/mdast/MdastFromMarkdown.js +79 -0
  193. package/dist/schemas/mdast/MdastFromMarkdown.js.map +1 -0
  194. package/dist/schemas/mdast/MdastSchema.d.ts +385 -0
  195. package/dist/schemas/mdast/MdastSchema.d.ts.map +1 -0
  196. package/dist/schemas/mdast/MdastSchema.js +266 -0
  197. package/dist/schemas/mdast/MdastSchema.js.map +1 -0
  198. package/dist/schemas/mdast/index.d.ts +10 -0
  199. package/dist/schemas/mdast/index.d.ts.map +1 -0
  200. package/dist/schemas/mdast/index.js +4 -0
  201. package/dist/schemas/mdast/index.js.map +1 -0
  202. package/dist/schemas/mdast/mdastToString.d.ts +13 -0
  203. package/dist/schemas/mdast/mdastToString.d.ts.map +1 -0
  204. package/dist/schemas/mdast/mdastToString.js +85 -0
  205. package/dist/schemas/mdast/mdastToString.js.map +1 -0
  206. package/dist/schemas/nodes/block/BlockSchema.d.ts +43 -0
  207. package/dist/schemas/nodes/block/BlockSchema.d.ts.map +1 -0
  208. package/dist/schemas/nodes/block/BlockSchema.js +634 -0
  209. package/dist/schemas/nodes/block/BlockSchema.js.map +1 -0
  210. package/dist/schemas/nodes/block/index.d.ts +7 -0
  211. package/dist/schemas/nodes/block/index.d.ts.map +1 -0
  212. package/dist/schemas/nodes/block/index.js +7 -0
  213. package/dist/schemas/nodes/block/index.js.map +1 -0
  214. package/dist/schemas/nodes/index.d.ts +9 -0
  215. package/dist/schemas/nodes/index.d.ts.map +1 -0
  216. package/dist/schemas/nodes/index.js +12 -0
  217. package/dist/schemas/nodes/index.js.map +1 -0
  218. package/dist/schemas/nodes/inline/InlineSchema.d.ts +48 -0
  219. package/dist/schemas/nodes/inline/InlineSchema.d.ts.map +1 -0
  220. package/dist/schemas/nodes/inline/InlineSchema.js +436 -0
  221. package/dist/schemas/nodes/inline/InlineSchema.js.map +1 -0
  222. package/dist/schemas/nodes/inline/index.d.ts +7 -0
  223. package/dist/schemas/nodes/inline/index.d.ts.map +1 -0
  224. package/dist/schemas/nodes/inline/index.js +7 -0
  225. package/dist/schemas/nodes/inline/index.js.map +1 -0
  226. package/dist/schemas/nodes/macro/MacroSchema.d.ts +27 -0
  227. package/dist/schemas/nodes/macro/MacroSchema.d.ts.map +1 -0
  228. package/dist/schemas/nodes/macro/MacroSchema.js +162 -0
  229. package/dist/schemas/nodes/macro/MacroSchema.js.map +1 -0
  230. package/dist/schemas/nodes/macro/index.d.ts +7 -0
  231. package/dist/schemas/nodes/macro/index.d.ts.map +1 -0
  232. package/dist/schemas/nodes/macro/index.js +7 -0
  233. package/dist/schemas/nodes/macro/index.js.map +1 -0
  234. package/dist/schemas/preprocessing/ConfluencePreprocessor.d.ts +24 -0
  235. package/dist/schemas/preprocessing/ConfluencePreprocessor.d.ts.map +1 -0
  236. package/dist/schemas/preprocessing/ConfluencePreprocessor.js +351 -0
  237. package/dist/schemas/preprocessing/ConfluencePreprocessor.js.map +1 -0
  238. package/dist/schemas/preprocessing/index.d.ts +8 -0
  239. package/dist/schemas/preprocessing/index.d.ts.map +1 -0
  240. package/dist/schemas/preprocessing/index.js +2 -0
  241. package/dist/schemas/preprocessing/index.js.map +1 -0
  242. package/dist/serializers/ConfluenceSerializer.d.ts +30 -0
  243. package/dist/serializers/ConfluenceSerializer.d.ts.map +1 -0
  244. package/dist/serializers/ConfluenceSerializer.js +551 -0
  245. package/dist/serializers/ConfluenceSerializer.js.map +1 -0
  246. package/dist/serializers/MarkdownSerializer.d.ts +34 -0
  247. package/dist/serializers/MarkdownSerializer.d.ts.map +1 -0
  248. package/dist/serializers/MarkdownSerializer.js +355 -0
  249. package/dist/serializers/MarkdownSerializer.js.map +1 -0
  250. package/dist/serializers/index.d.ts +8 -0
  251. package/dist/serializers/index.d.ts.map +1 -0
  252. package/dist/serializers/index.js +8 -0
  253. package/dist/serializers/index.js.map +1 -0
  254. package/package.json +27 -16
  255. package/src/ConfluenceAuth.ts +571 -0
  256. package/src/ConfluenceClient.ts +188 -156
  257. package/src/ConfluenceConfig.ts +63 -7
  258. package/src/ConfluenceError.ts +110 -14
  259. package/src/GitError.ts +92 -0
  260. package/src/GitService.ts +859 -0
  261. package/src/LocalFileSystem.ts +179 -9
  262. package/src/MarkdownConverter.ts +126 -122
  263. package/src/SchemaConverterError.ts +108 -0
  264. package/src/Schemas.ts +223 -6
  265. package/src/SyncEngine.ts +745 -162
  266. package/src/ast/BlockNode.ts +425 -0
  267. package/src/ast/Document.ts +90 -0
  268. package/src/ast/InlineNode.ts +323 -0
  269. package/src/ast/MacroNode.ts +245 -0
  270. package/src/ast/index.ts +83 -0
  271. package/src/bin.ts +50 -249
  272. package/src/commands/auth.ts +117 -0
  273. package/src/commands/clone.ts +145 -0
  274. package/src/commands/delete.ts +57 -0
  275. package/src/commands/errorHandler.ts +32 -0
  276. package/src/commands/git.ts +114 -0
  277. package/src/commands/index.ts +10 -0
  278. package/src/commands/layers.ts +211 -0
  279. package/src/commands/new.ts +99 -0
  280. package/src/commands/pageTree.ts +40 -0
  281. package/src/commands/shared.ts +35 -0
  282. package/src/commands/sync.ts +129 -0
  283. package/src/index.ts +21 -1
  284. package/src/internal/NodeLayers.ts +21 -0
  285. package/src/internal/frontmatter.ts +21 -0
  286. package/src/internal/gitCommands.ts +229 -0
  287. package/src/internal/hashUtils.ts +65 -3
  288. package/src/internal/oauthServer.ts +199 -0
  289. package/src/internal/pathUtils.ts +34 -17
  290. package/src/internal/tokenStorage.ts +240 -0
  291. package/src/internal/userCache.ts +90 -0
  292. package/src/parsers/ConfluenceParser.ts +950 -0
  293. package/src/parsers/MarkdownParser.ts +1198 -0
  294. package/src/parsers/index.ts +8 -0
  295. package/src/schemas/ConfluenceSchema.ts +56 -0
  296. package/src/schemas/ConversionSchema.ts +318 -0
  297. package/src/schemas/MarkdownSchema.ts +56 -0
  298. package/src/schemas/hast/HastFromHtml.ts +153 -0
  299. package/src/schemas/hast/HastSchema.ts +274 -0
  300. package/src/schemas/hast/index.ts +35 -0
  301. package/src/schemas/index.ts +20 -0
  302. package/src/schemas/mdast/MdastFromMarkdown.ts +118 -0
  303. package/src/schemas/mdast/MdastSchema.ts +566 -0
  304. package/src/schemas/mdast/index.ts +59 -0
  305. package/src/schemas/mdast/mdastToString.ts +102 -0
  306. package/src/schemas/nodes/block/BlockSchema.ts +773 -0
  307. package/src/schemas/nodes/block/index.ts +13 -0
  308. package/src/schemas/nodes/index.ts +20 -0
  309. package/src/schemas/nodes/inline/InlineSchema.ts +523 -0
  310. package/src/schemas/nodes/inline/index.ts +14 -0
  311. package/src/schemas/nodes/macro/MacroSchema.ts +226 -0
  312. package/src/schemas/nodes/macro/index.ts +6 -0
  313. package/src/schemas/preprocessing/ConfluencePreprocessor.ts +446 -0
  314. package/src/schemas/preprocessing/index.ts +8 -0
  315. package/src/serializers/ConfluenceSerializer.ts +717 -0
  316. package/src/serializers/MarkdownSerializer.ts +493 -0
  317. package/src/serializers/index.ts +8 -0
  318. package/test/GitService.test.ts +209 -0
  319. package/test/MarkdownConverter.test.ts +37 -3
  320. package/test/Schemas.test.ts +97 -2
  321. package/test/ast/BlockNode.test.ts +265 -0
  322. package/test/ast/Document.test.ts +126 -0
  323. package/test/ast/InlineNode.test.ts +161 -0
  324. package/test/fixtures/integration-test.html.fixture +103 -0
  325. package/test/fixtures/integration-test.md.expected +257 -0
  326. package/test/integration.test.ts +269 -0
  327. package/test/oauthServer.test.ts +50 -0
  328. package/test/parsers/ConfluenceParser.test.ts +283 -0
  329. package/test/schemas/ConfluencePreprocessor.test.ts +180 -0
  330. package/test/schemas/ConversionSchema.test.ts +159 -0
  331. package/test/schemas/HastSchema.test.ts +138 -0
  332. package/test/schemas/MdastSchema.test.ts +145 -0
  333. package/test/schemas/nodes/block/BlockSchema.test.ts +173 -0
  334. package/test/schemas/nodes/inline/InlineSchema.test.ts +198 -0
  335. package/test/schemas/nodes/macro/MacroSchema.test.ts +142 -0
  336. package/test/tokenStorage.test.ts +99 -0
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Block node transform schemas.
3
+ *
4
+ * @module
5
+ */
6
+ export {
7
+ blockNodeFromHastElement,
8
+ blockNodeFromMdast,
9
+ BlockNodesFromHast,
10
+ BlockNodesFromMdast,
11
+ blockNodeToHast,
12
+ blockNodeToMdast
13
+ } from "./BlockSchema.js"
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Node transform schemas for all AST node types.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ // Re-export inline node schemas
8
+ export {
9
+ inlineNodeFromHastElement,
10
+ inlineNodeFromMdast,
11
+ inlineNodeToHast,
12
+ inlineNodeToMdast,
13
+ textFromHastText
14
+ } from "./inline/index.js"
15
+
16
+ // Re-export block node schemas
17
+ export { blockNodeFromHastElement, blockNodeFromMdast, blockNodeToHast, blockNodeToMdast } from "./block/index.js"
18
+
19
+ // Re-export macro node schemas
20
+ export { macroNodeFromHastElement, macroNodeToHast, macroNodeToMdast } from "./macro/index.js"
@@ -0,0 +1,523 @@
1
+ /**
2
+ * Transform schemas for inline nodes (Hast <-> AST <-> Mdast).
3
+ *
4
+ * Provides bidirectional transforms between HAST elements, AST inline nodes,
5
+ * and MDAST phrasing content for text-level formatting.
6
+ *
7
+ * @module
8
+ */
9
+ import * as Effect from "effect/Effect"
10
+ import * as ParseResult from "effect/ParseResult"
11
+ import * as Schema from "effect/Schema"
12
+ import {
13
+ ColoredText,
14
+ DateTime,
15
+ Emoticon,
16
+ Emphasis,
17
+ Highlight,
18
+ InlineCode,
19
+ type InlineNode,
20
+ LineBreak,
21
+ Link,
22
+ Strikethrough,
23
+ Strong,
24
+ Subscript,
25
+ Superscript,
26
+ Text,
27
+ Underline,
28
+ UnsupportedInline,
29
+ UserMention
30
+ } from "../../../ast/InlineNode.js"
31
+ import type { HastElement, HastNode, HastText } from "../../hast/index.js"
32
+ import { getTextContent, isHastElement, isHastText, makeHastElement, makeHastText } from "../../hast/index.js"
33
+ import type { MdastPhrasingContent } from "../../mdast/index.js"
34
+ import { makeMdastText } from "../../mdast/index.js"
35
+
36
+ /**
37
+ * Convert HAST text node to AST Text.
38
+ */
39
+ export const textFromHastText = (node: HastText): Text => new Text({ value: node.value })
40
+
41
+ /**
42
+ * Convert HAST element to AST inline node.
43
+ */
44
+ export const inlineNodeFromHastElement = (
45
+ element: HastElement,
46
+ parseChildren: (children: ReadonlyArray<HastNode>) => Effect.Effect<ReadonlyArray<InlineNode>, ParseResult.ParseError>
47
+ ): Effect.Effect<InlineNode | null, ParseResult.ParseError> =>
48
+ Effect.gen(function*() {
49
+ const tagName = element.tagName.toLowerCase()
50
+
51
+ // Strong/bold
52
+ if (tagName === "strong" || tagName === "b") {
53
+ const children = yield* parseChildrenToBase(element.children, parseChildren)
54
+ return new Strong({ children })
55
+ }
56
+
57
+ // Emphasis/italic
58
+ if (tagName === "em" || tagName === "i") {
59
+ const children = yield* parseChildrenToBase(element.children, parseChildren)
60
+ return new Emphasis({ children })
61
+ }
62
+
63
+ // Underline
64
+ if (tagName === "u") {
65
+ const children = yield* parseChildrenToBase(element.children, parseChildren)
66
+ return new Underline({ children })
67
+ }
68
+
69
+ // Strikethrough
70
+ if (tagName === "del" || tagName === "s") {
71
+ const children = yield* parseChildrenToBase(element.children, parseChildren)
72
+ return new Strikethrough({ children })
73
+ }
74
+
75
+ // Subscript
76
+ if (tagName === "sub") {
77
+ const children = yield* parseChildrenToBase(element.children, parseChildren)
78
+ return new Subscript({ children })
79
+ }
80
+
81
+ // Superscript
82
+ if (tagName === "sup") {
83
+ const children = yield* parseChildrenToBase(element.children, parseChildren)
84
+ return new Superscript({ children })
85
+ }
86
+
87
+ // Inline code
88
+ if (tagName === "code") {
89
+ return new InlineCode({ value: getTextContent(element) })
90
+ }
91
+
92
+ // Link
93
+ if (tagName === "a") {
94
+ const href = element.properties?.href as string | undefined
95
+ if (!href) return null
96
+ const children = yield* parseChildrenToBase(element.children, parseChildren)
97
+ return new Link({
98
+ href,
99
+ title: (element.properties?.title as string) || undefined,
100
+ children
101
+ })
102
+ }
103
+
104
+ // Line break
105
+ if (tagName === "br") {
106
+ return new LineBreak({})
107
+ }
108
+
109
+ // Date/time
110
+ if (tagName === "time") {
111
+ const datetime = (element.properties?.dateTime as string) || ""
112
+ return new DateTime({ datetime })
113
+ }
114
+
115
+ // Emoticon (preprocessed from ac:emoticon)
116
+ if (tagName === "span" && element.properties?.["dataEmoji"]) {
117
+ const shortname = (element.properties["dataEmoji"] as string) || ""
118
+ const emojiId = (element.properties["dataEmojiId"] as string) || ""
119
+ const fallback = getTextContent(element)
120
+ return new Emoticon({ shortname, emojiId, fallback })
121
+ }
122
+
123
+ // User mention (preprocessed from ac:link > ri:user)
124
+ if (tagName === "span" && element.properties?.["dataUserMention"]) {
125
+ const accountId = (element.properties["dataUserMention"] as string) || ""
126
+ return new UserMention({ accountId })
127
+ }
128
+
129
+ // Confluence link with link-body (preprocessed from ac:link > ac:link-body)
130
+ if (tagName === "span" && element.properties?.["dataConfluenceLink"] !== undefined) {
131
+ const linkText = getTextContent(element)
132
+ return new UnsupportedInline({
133
+ raw: `<!--cf:link:${encodeURIComponent(linkText)}-->`,
134
+ source: "confluence"
135
+ })
136
+ }
137
+
138
+ // Colored text (span with color style)
139
+ if (tagName === "span") {
140
+ const style = element.properties?.style as string | undefined
141
+ if (style) {
142
+ const colorMatch = style.match(/(?:^|;)\s*color:\s*([^;]+)/)
143
+ const bgMatch = style.match(/(?:^|;)\s*background-color:\s*([^;]+)/)
144
+
145
+ if (colorMatch?.[1]) {
146
+ const children = yield* parseChildrenToBase(element.children, parseChildren)
147
+ return new ColoredText({ color: colorMatch[1].trim(), children })
148
+ }
149
+
150
+ if (bgMatch?.[1]) {
151
+ const children = yield* parseChildrenToBase(element.children, parseChildren)
152
+ return new Highlight({ backgroundColor: bgMatch[1].trim(), children })
153
+ }
154
+ }
155
+
156
+ // Nested span - extract single child
157
+ const children = yield* parseChildren(element.children)
158
+ if (children.length === 1) {
159
+ return children[0] ?? null
160
+ }
161
+ return null
162
+ }
163
+
164
+ // Unknown inline element
165
+ return new UnsupportedInline({
166
+ raw: hastElementToHtml(element),
167
+ source: "confluence"
168
+ })
169
+ })
170
+
171
+ /**
172
+ * Convert AST inline node to HAST node.
173
+ */
174
+ export const inlineNodeToHast = (node: InlineNode): HastNode => {
175
+ switch (node._tag) {
176
+ case "Text":
177
+ return makeHastText(node.value)
178
+ case "Strong":
179
+ return makeHastElement("strong", {}, node.children.map(inlineNodeToHast))
180
+ case "Emphasis":
181
+ return makeHastElement("em", {}, node.children.map(inlineNodeToHast))
182
+ case "InlineCode":
183
+ return makeHastElement("code", {}, [makeHastText(node.value)])
184
+ case "Link":
185
+ return makeHastElement(
186
+ "a",
187
+ { href: node.href, ...(node.title ? { title: node.title } : {}) },
188
+ node.children.map(inlineNodeToHast)
189
+ )
190
+ case "LineBreak":
191
+ return makeHastElement("br")
192
+ case "DateTime":
193
+ return makeHastElement("time", { dateTime: node.datetime }, [makeHastText(node.datetime)])
194
+ case "Emoticon":
195
+ return makeHastElement(
196
+ "span",
197
+ { dataEmoji: node.shortname, dataEmojiId: node.emojiId },
198
+ [makeHastText(node.fallback)]
199
+ )
200
+ case "UserMention":
201
+ return makeHastElement("span", { dataUserMention: node.accountId })
202
+ case "Underline":
203
+ return makeHastElement("u", {}, node.children.map(inlineNodeToHast))
204
+ case "Subscript":
205
+ return makeHastElement("sub", {}, node.children.map(inlineNodeToHast))
206
+ case "Superscript":
207
+ return makeHastElement("sup", {}, node.children.map(inlineNodeToHast))
208
+ case "Strikethrough":
209
+ return makeHastElement("del", {}, node.children.map(inlineNodeToHast))
210
+ case "ColoredText":
211
+ return makeHastElement("span", { style: `color: ${node.color}` }, node.children.map(inlineNodeToHast))
212
+ case "Highlight":
213
+ return makeHastElement(
214
+ "span",
215
+ { style: `background-color: ${node.backgroundColor}` },
216
+ node.children.map(inlineNodeToHast)
217
+ )
218
+ case "UnsupportedInline":
219
+ // Return raw HTML wrapped in span
220
+ return makeHastElement("span", { dangerouslySetInnerHTML: node.raw })
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Convert AST inline node to MDAST phrasing content.
226
+ */
227
+ export const inlineNodeToMdast = (node: InlineNode): MdastPhrasingContent => {
228
+ switch (node._tag) {
229
+ case "Text":
230
+ return makeMdastText(node.value)
231
+ case "Strong":
232
+ return {
233
+ type: "strong",
234
+ children: node.children.map(inlineNodeToMdast)
235
+ }
236
+ case "Emphasis":
237
+ return {
238
+ type: "emphasis",
239
+ children: node.children.map(inlineNodeToMdast)
240
+ }
241
+ case "InlineCode":
242
+ return {
243
+ type: "inlineCode",
244
+ value: node.value
245
+ }
246
+ case "Link":
247
+ return {
248
+ type: "link",
249
+ url: node.href,
250
+ title: node.title ?? null,
251
+ children: node.children.map(inlineNodeToMdast)
252
+ }
253
+ case "LineBreak":
254
+ return { type: "break" }
255
+ case "DateTime":
256
+ // Markdown doesn't have native datetime - render as text
257
+ return makeMdastText(node.datetime)
258
+ case "Emoticon":
259
+ // Render emoji fallback
260
+ return makeMdastText(node.fallback || node.shortname)
261
+ case "UserMention":
262
+ // Render as @mention text
263
+ return makeMdastText(`@${node.accountId}`)
264
+ case "Underline":
265
+ // Markdown doesn't have underline - render as HTML
266
+ return {
267
+ type: "html",
268
+ value: `<u>${node.children.map((c) => inlineNodeToMdastText(c)).join("")}</u>`
269
+ }
270
+ case "Subscript":
271
+ return {
272
+ type: "html",
273
+ value: `<sub>${node.children.map((c) => inlineNodeToMdastText(c)).join("")}</sub>`
274
+ }
275
+ case "Superscript":
276
+ return {
277
+ type: "html",
278
+ value: `<sup>${node.children.map((c) => inlineNodeToMdastText(c)).join("")}</sup>`
279
+ }
280
+ case "Strikethrough":
281
+ return {
282
+ type: "delete",
283
+ children: node.children.map(inlineNodeToMdast)
284
+ }
285
+ case "ColoredText":
286
+ // Markdown doesn't have colored text - render as plain text
287
+ return makeMdastText(node.children.map((c) => inlineNodeToMdastText(c)).join(""))
288
+ case "Highlight":
289
+ // Markdown doesn't have highlight - render as plain text
290
+ return makeMdastText(node.children.map((c) => inlineNodeToMdastText(c)).join(""))
291
+ case "UnsupportedInline":
292
+ return {
293
+ type: "html",
294
+ value: node.raw
295
+ }
296
+ }
297
+ }
298
+
299
+ /**
300
+ * Base inline node type for children of Strong/Emphasis/Link.
301
+ */
302
+ type BaseInlineNode = Text | InlineCode | LineBreak | UnsupportedInline | Emoticon | UserMention | DateTime
303
+
304
+ /**
305
+ * Convert full InlineNode to base type (for Strong/Emphasis/Link children).
306
+ * Complex nodes are converted to UnsupportedInline.
307
+ */
308
+ const toBaseInlineNode = (node: InlineNode): BaseInlineNode => {
309
+ switch (node._tag) {
310
+ case "Text":
311
+ case "InlineCode":
312
+ case "LineBreak":
313
+ case "UnsupportedInline":
314
+ case "Emoticon":
315
+ case "UserMention":
316
+ case "DateTime":
317
+ return node
318
+ case "Strong":
319
+ case "Emphasis":
320
+ case "Link":
321
+ case "Underline":
322
+ case "Subscript":
323
+ case "Superscript":
324
+ case "Strikethrough":
325
+ case "ColoredText":
326
+ case "Highlight":
327
+ // Flatten complex nodes to plain text
328
+ return new Text({ value: inlineNodeToMdastText(node) })
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Convert MDAST phrasing content to AST inline node.
334
+ */
335
+ export const inlineNodeFromMdast = (node: MdastPhrasingContent): InlineNode => {
336
+ switch (node.type) {
337
+ case "text":
338
+ return new Text({ value: node.value })
339
+ case "strong":
340
+ return new Strong({ children: node.children.map(inlineNodeFromMdast).map(toBaseInlineNode) })
341
+ case "emphasis":
342
+ return new Emphasis({ children: node.children.map(inlineNodeFromMdast).map(toBaseInlineNode) })
343
+ case "inlineCode":
344
+ return new InlineCode({ value: node.value })
345
+ case "link":
346
+ return new Link({
347
+ href: node.url,
348
+ title: node.title ?? undefined,
349
+ children: node.children.map(inlineNodeFromMdast).map(toBaseInlineNode)
350
+ })
351
+ case "break":
352
+ return new LineBreak({})
353
+ case "image":
354
+ // Inline images become unsupported
355
+ return new UnsupportedInline({
356
+ raw: `![${node.alt ?? ""}](${node.url})`,
357
+ source: "markdown"
358
+ })
359
+ case "delete":
360
+ return new Strikethrough({ children: node.children.map(inlineNodeFromMdast).map(toBaseInlineNode) })
361
+ case "html":
362
+ return new UnsupportedInline({ raw: node.value, source: "markdown" })
363
+ default:
364
+ return new UnsupportedInline({
365
+ raw: JSON.stringify(node),
366
+ source: "markdown"
367
+ })
368
+ }
369
+ }
370
+
371
+ // Helper functions
372
+
373
+ /**
374
+ * Parse HAST children to base inline nodes (for Strong/Emphasis/Link children).
375
+ */
376
+ const parseChildrenToBase = (
377
+ children: ReadonlyArray<HastNode>,
378
+ _parseChildren: (
379
+ children: ReadonlyArray<HastNode>
380
+ ) => Effect.Effect<ReadonlyArray<InlineNode>, ParseResult.ParseError>
381
+ ): Effect.Effect<ReadonlyArray<Text | InlineCode | LineBreak | UnsupportedInline>, ParseResult.ParseError> =>
382
+ Effect.gen(function*() {
383
+ const nodes: Array<Text | InlineCode | LineBreak | UnsupportedInline> = []
384
+ for (const child of children) {
385
+ if (isHastText(child)) {
386
+ nodes.push(new Text({ value: child.value }))
387
+ } else if (isHastElement(child)) {
388
+ const tagName = child.tagName.toLowerCase()
389
+ if (tagName === "code") {
390
+ nodes.push(new InlineCode({ value: getTextContent(child) }))
391
+ } else if (tagName === "br") {
392
+ nodes.push(new LineBreak({}))
393
+ } else {
394
+ nodes.push(new UnsupportedInline({ raw: hastElementToHtml(child), source: "confluence" }))
395
+ }
396
+ }
397
+ }
398
+ return nodes
399
+ })
400
+
401
+ /**
402
+ * Extract plain text from inline node.
403
+ */
404
+ const inlineNodeToMdastText = (node: InlineNode): string => {
405
+ switch (node._tag) {
406
+ case "Text":
407
+ return node.value
408
+ case "InlineCode":
409
+ return node.value
410
+ case "LineBreak":
411
+ return "\n"
412
+ case "DateTime":
413
+ return node.datetime
414
+ case "Emoticon":
415
+ return node.fallback || node.shortname
416
+ case "UserMention":
417
+ return `@${node.accountId}`
418
+ case "Strong":
419
+ case "Emphasis":
420
+ case "Underline":
421
+ case "Subscript":
422
+ case "Superscript":
423
+ case "Strikethrough":
424
+ case "ColoredText":
425
+ case "Highlight":
426
+ return node.children.map(inlineNodeToMdastText).join("")
427
+ case "Link":
428
+ return node.children.map(inlineNodeToMdastText).join("")
429
+ case "UnsupportedInline":
430
+ return ""
431
+ }
432
+ }
433
+
434
+ /**
435
+ * Convert HAST element to HTML string.
436
+ */
437
+ const hastElementToHtml = (element: HastElement): string => {
438
+ const props = Object.entries(element.properties || {})
439
+ .map(([k, v]) => {
440
+ const attrName = k.replace(/([A-Z])/g, "-$1").toLowerCase()
441
+ return `${attrName}="${String(v)}"`
442
+ })
443
+ .join(" ")
444
+ const openTag = props ? `<${element.tagName} ${props}>` : `<${element.tagName}>`
445
+ const closeTag = `</${element.tagName}>`
446
+ const content = element.children
447
+ .map((c) => {
448
+ if (isHastText(c)) return c.value
449
+ if (isHastElement(c)) return hastElementToHtml(c)
450
+ return ""
451
+ })
452
+ .join("")
453
+ return `${openTag}${content}${closeTag}`
454
+ }
455
+
456
+ /**
457
+ * Schema-based HAST to InlineNode array transform.
458
+ * This is the main transform schema for parsing inline content from HAST.
459
+ *
460
+ * @category Schemas
461
+ */
462
+ export const InlineNodesFromHast = Schema.transformOrFail(
463
+ Schema.Array(Schema.Unknown),
464
+ Schema.Array(Schema.Any),
465
+ {
466
+ strict: false,
467
+ decode: (hastNodes, _options, ast) =>
468
+ Effect.gen(function*() {
469
+ const results: Array<InlineNode> = []
470
+
471
+ const parseChildren = (children: ReadonlyArray<HastNode>): Effect.Effect<
472
+ ReadonlyArray<InlineNode>,
473
+ ParseResult.ParseError
474
+ > =>
475
+ Effect.gen(function*() {
476
+ const childResults: Array<InlineNode> = []
477
+ for (const child of children) {
478
+ if (isHastText(child)) {
479
+ childResults.push(textFromHastText(child))
480
+ } else if (isHastElement(child)) {
481
+ const node = yield* inlineNodeFromHastElement(child, parseChildren)
482
+ if (node) childResults.push(node)
483
+ }
484
+ }
485
+ return childResults
486
+ })
487
+
488
+ for (const hastNode of hastNodes) {
489
+ if (isHastText(hastNode as HastNode)) {
490
+ results.push(textFromHastText(hastNode as HastText))
491
+ } else if (isHastElement(hastNode as HastNode)) {
492
+ const node = yield* inlineNodeFromHastElement(hastNode as HastElement, parseChildren)
493
+ if (node) results.push(node)
494
+ }
495
+ }
496
+
497
+ return results
498
+ }).pipe(
499
+ Effect.mapError((e) =>
500
+ e instanceof ParseResult.ParseError
501
+ ? e.issue
502
+ : new ParseResult.Type(ast, hastNodes, String(e))
503
+ )
504
+ ),
505
+ encode: (nodes, _options, _ast) => Effect.succeed(nodes.map(inlineNodeToHast) as ReadonlyArray<unknown>)
506
+ }
507
+ )
508
+
509
+ /**
510
+ * Schema-based MDAST to InlineNode array transform.
511
+ *
512
+ * @category Schemas
513
+ */
514
+ export const InlineNodesFromMdast = Schema.transformOrFail(
515
+ Schema.Array(Schema.Unknown),
516
+ Schema.Array(Schema.Any),
517
+ {
518
+ strict: false,
519
+ decode: (mdastNodes, _options, _ast) =>
520
+ Effect.succeed(mdastNodes.map((n) => inlineNodeFromMdast(n as MdastPhrasingContent))),
521
+ encode: (nodes, _options, _ast) => Effect.succeed(nodes.map(inlineNodeToMdast) as ReadonlyArray<unknown>)
522
+ }
523
+ )
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Inline node transform schemas.
3
+ *
4
+ * @module
5
+ */
6
+ export {
7
+ inlineNodeFromHastElement,
8
+ inlineNodeFromMdast,
9
+ InlineNodesFromHast,
10
+ InlineNodesFromMdast,
11
+ inlineNodeToHast,
12
+ inlineNodeToMdast,
13
+ textFromHastText
14
+ } from "./InlineSchema.js"