@knpkv/confluence-to-markdown 0.2.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (336) hide show
  1. package/CHANGELOG.md +73 -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 +366 -0
  7. package/dist/ConfluenceAuth.js.map +1 -0
  8. package/dist/ConfluenceClient.d.ts +26 -12
  9. package/dist/ConfluenceClient.d.ts.map +1 -1
  10. package/dist/ConfluenceClient.js +139 -97
  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 +99 -16
  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 +32 -21
  255. package/src/ConfluenceAuth.ts +581 -0
  256. package/src/ConfluenceClient.ts +230 -165
  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
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from "@effect/vitest"
2
2
  import * as Effect from "effect/Effect"
3
- import { layer as MarkdownConverterLayer, MarkdownConverter } from "../src/MarkdownConverter.js"
3
+ import { layer as MarkdownConverterLayer, MarkdownConverter, schemaBasedLayer } from "../src/MarkdownConverter.js"
4
4
 
5
5
  describe("MarkdownConverter", () => {
6
6
  describe("htmlToMarkdown", () => {
@@ -27,8 +27,9 @@ describe("MarkdownConverter", () => {
27
27
  const converter = yield* MarkdownConverter
28
28
  const html = "<ul><li>Item 1</li><li>Item 2</li></ul>"
29
29
  const markdown = yield* converter.htmlToMarkdown(html)
30
- expect(markdown).toContain("* Item 1")
31
- expect(markdown).toContain("* Item 2")
30
+ // AST-based serializer uses - for unordered lists
31
+ expect(markdown).toContain("- Item 1")
32
+ expect(markdown).toContain("- Item 2")
32
33
  }).pipe(Effect.provide(MarkdownConverterLayer)))
33
34
 
34
35
  it.effect("converts links", () =>
@@ -105,4 +106,37 @@ describe("MarkdownConverter", () => {
105
106
  expect(html).toContain("checkbox")
106
107
  }).pipe(Effect.provide(MarkdownConverterLayer)))
107
108
  })
109
+
110
+ describe("schemaBasedLayer", () => {
111
+ it.effect("htmlToMarkdown converts basic HTML", () =>
112
+ Effect.gen(function*() {
113
+ const converter = yield* MarkdownConverter
114
+ const html = "<h1>Title</h1><p>Hello world</p>"
115
+ const markdown = yield* converter.htmlToMarkdown(html)
116
+ expect(markdown).toContain("# Title")
117
+ expect(markdown).toContain("Hello world")
118
+ }).pipe(Effect.provide(schemaBasedLayer)))
119
+
120
+ it.effect("htmlToAst parses HTML to Document", () =>
121
+ Effect.gen(function*() {
122
+ const converter = yield* MarkdownConverter
123
+ const html = "<h1>Title</h1><p>Content</p>"
124
+ const doc = yield* converter.htmlToAst(html)
125
+ expect(doc.version).toBe(1)
126
+ expect(doc.children.length).toBe(2)
127
+ expect(doc.children[0]?._tag).toBe("Heading")
128
+ expect(doc.children[1]?._tag).toBe("Paragraph")
129
+ }).pipe(Effect.provide(schemaBasedLayer)))
130
+
131
+ it.effect("markdownToAst parses Markdown to Document", () =>
132
+ Effect.gen(function*() {
133
+ const converter = yield* MarkdownConverter
134
+ const md = "# Title\n\nContent"
135
+ const doc = yield* converter.markdownToAst(md)
136
+ expect(doc.version).toBe(1)
137
+ expect(doc.children.length).toBe(2)
138
+ expect(doc.children[0]?._tag).toBe("Heading")
139
+ expect(doc.children[1]?._tag).toBe("Paragraph")
140
+ }).pipe(Effect.provide(schemaBasedLayer)))
141
+ })
108
142
  })
@@ -2,7 +2,13 @@ import { describe, expect, it } from "@effect/vitest"
2
2
  import * as Either from "effect/Either"
3
3
  import * as Schema from "effect/Schema"
4
4
  import type { ContentHash, PageId } from "../src/Brand.js"
5
- import { ConfluenceConfigFileSchema, PageFrontMatterSchema } from "../src/Schemas.js"
5
+ import {
6
+ ConfluenceConfigFileSchema,
7
+ OAuthConfigSchema,
8
+ OAuthTokenSchema,
9
+ OAuthUserSchema,
10
+ PageFrontMatterSchema
11
+ } from "../src/Schemas.js"
6
12
 
7
13
  describe("Schemas", () => {
8
14
  describe("ConfluenceConfigFileSchema", () => {
@@ -14,7 +20,7 @@ describe("Schemas", () => {
14
20
  const result = Schema.decodeUnknownEither(ConfluenceConfigFileSchema)(config)
15
21
  expect(Either.isRight(result)).toBe(true)
16
22
  if (Either.isRight(result)) {
17
- expect(result.right.docsPath).toBe(".docs/confluence")
23
+ expect(result.right.docsPath).toBe(".confluence/docs")
18
24
  expect(result.right.excludePatterns).toEqual([])
19
25
  }
20
26
  })
@@ -96,4 +102,93 @@ describe("Schemas", () => {
96
102
  expect(Either.isLeft(result)).toBe(true)
97
103
  })
98
104
  })
105
+
106
+ describe("OAuthTokenSchema", () => {
107
+ it("decodes valid token", () => {
108
+ const token = {
109
+ access_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
110
+ refresh_token: "refresh_token_value",
111
+ expires_at: Date.now() + 3600000,
112
+ scope: "read:confluence-content.all",
113
+ cloud_id: "abc123",
114
+ site_url: "https://mysite.atlassian.net"
115
+ }
116
+ const result = Schema.decodeUnknownEither(OAuthTokenSchema)(token)
117
+ expect(Either.isRight(result)).toBe(true)
118
+ })
119
+
120
+ it("decodes token with user info", () => {
121
+ const token = {
122
+ access_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
123
+ refresh_token: "refresh_token_value",
124
+ expires_at: Date.now() + 3600000,
125
+ scope: "read:confluence-content.all",
126
+ cloud_id: "abc123",
127
+ site_url: "https://mysite.atlassian.net",
128
+ user: {
129
+ account_id: "user123",
130
+ name: "Test User",
131
+ email: "test@example.com"
132
+ }
133
+ }
134
+ const result = Schema.decodeUnknownEither(OAuthTokenSchema)(token)
135
+ expect(Either.isRight(result)).toBe(true)
136
+ if (Either.isRight(result)) {
137
+ expect(result.right.user?.name).toBe("Test User")
138
+ }
139
+ })
140
+
141
+ it("rejects missing required fields", () => {
142
+ const token = {
143
+ access_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
144
+ // missing refresh_token
145
+ expires_at: Date.now() + 3600000,
146
+ scope: "read:confluence-content.all",
147
+ cloud_id: "abc123",
148
+ site_url: "https://mysite.atlassian.net"
149
+ }
150
+ const result = Schema.decodeUnknownEither(OAuthTokenSchema)(token)
151
+ expect(Either.isLeft(result)).toBe(true)
152
+ })
153
+ })
154
+
155
+ describe("OAuthConfigSchema", () => {
156
+ it("decodes valid config", () => {
157
+ const config = {
158
+ clientId: "client_id_value",
159
+ clientSecret: "client_secret_value"
160
+ }
161
+ const result = Schema.decodeUnknownEither(OAuthConfigSchema)(config)
162
+ expect(Either.isRight(result)).toBe(true)
163
+ })
164
+
165
+ it("rejects missing clientSecret", () => {
166
+ const config = {
167
+ clientId: "client_id_value"
168
+ }
169
+ const result = Schema.decodeUnknownEither(OAuthConfigSchema)(config)
170
+ expect(Either.isLeft(result)).toBe(true)
171
+ })
172
+ })
173
+
174
+ describe("OAuthUserSchema", () => {
175
+ it("decodes valid user info", () => {
176
+ const user = {
177
+ account_id: "user123",
178
+ name: "Test User",
179
+ email: "test@example.com"
180
+ }
181
+ const result = Schema.decodeUnknownEither(OAuthUserSchema)(user)
182
+ expect(Either.isRight(result)).toBe(true)
183
+ })
184
+
185
+ it("rejects missing email", () => {
186
+ const user = {
187
+ account_id: "user123",
188
+ name: "Test User"
189
+ }
190
+ const result = Schema.decodeUnknownEither(OAuthUserSchema)(user)
191
+ expect(Either.isLeft(result)).toBe(true)
192
+ })
193
+ })
99
194
  })
@@ -0,0 +1,265 @@
1
+ import { describe, expect, it } from "@effect/vitest"
2
+ import * as Either from "effect/Either"
3
+ import * as Schema from "effect/Schema"
4
+ import {
5
+ BlockNode,
6
+ BlockQuote,
7
+ CodeBlock,
8
+ Heading,
9
+ Image,
10
+ List,
11
+ ListItem,
12
+ Paragraph,
13
+ Table,
14
+ TableCell,
15
+ TableRow,
16
+ ThematicBreak,
17
+ UnsupportedBlock
18
+ } from "../../src/ast/BlockNode.js"
19
+ import { Text } from "../../src/ast/InlineNode.js"
20
+
21
+ describe("BlockNode", () => {
22
+ describe("Heading", () => {
23
+ it("creates heading with level and children", () => {
24
+ const h1 = new Heading({
25
+ level: 1,
26
+ children: [new Text({ value: "Title" })]
27
+ })
28
+ expect(h1._tag).toBe("Heading")
29
+ expect(h1.level).toBe(1)
30
+ expect(h1.version).toBe(1)
31
+ })
32
+
33
+ it("decodes heading from plain object", () => {
34
+ const result = Schema.decodeUnknownEither(Heading)({
35
+ _tag: "Heading",
36
+ level: 2,
37
+ children: [{ _tag: "Text", value: "Subtitle" }]
38
+ })
39
+ expect(Either.isRight(result)).toBe(true)
40
+ if (Either.isRight(result)) {
41
+ expect(result.right.level).toBe(2)
42
+ expect(result.right.version).toBe(1)
43
+ }
44
+ })
45
+
46
+ it("rejects invalid level", () => {
47
+ const result = Schema.decodeUnknownEither(Heading)({
48
+ _tag: "Heading",
49
+ level: 7,
50
+ children: []
51
+ })
52
+ expect(Either.isLeft(result)).toBe(true)
53
+ })
54
+ })
55
+
56
+ describe("Paragraph", () => {
57
+ it("creates paragraph with children", () => {
58
+ const para = new Paragraph({
59
+ children: [new Text({ value: "Hello" })]
60
+ })
61
+ expect(para._tag).toBe("Paragraph")
62
+ expect(para.children).toHaveLength(1)
63
+ })
64
+ })
65
+
66
+ describe("CodeBlock", () => {
67
+ it("creates code block with language", () => {
68
+ const code = new CodeBlock({
69
+ language: "typescript",
70
+ code: "const x = 1"
71
+ })
72
+ expect(code._tag).toBe("CodeBlock")
73
+ expect(code.language).toBe("typescript")
74
+ expect(code.code).toBe("const x = 1")
75
+ })
76
+
77
+ it("creates code block without language", () => {
78
+ const code = new CodeBlock({ code: "plain text" })
79
+ expect(code.language).toBeUndefined()
80
+ })
81
+ })
82
+
83
+ describe("ThematicBreak", () => {
84
+ it("creates thematic break", () => {
85
+ const hr = new ThematicBreak({})
86
+ expect(hr._tag).toBe("ThematicBreak")
87
+ })
88
+ })
89
+
90
+ describe("Image", () => {
91
+ it("creates image with src", () => {
92
+ const img = new Image({
93
+ src: "https://example.com/img.png"
94
+ })
95
+ expect(img._tag).toBe("Image")
96
+ expect(img.src).toBe("https://example.com/img.png")
97
+ })
98
+
99
+ it("creates image with alt and title", () => {
100
+ const img = new Image({
101
+ src: "https://example.com/img.png",
102
+ alt: "Alt text",
103
+ title: "Image title"
104
+ })
105
+ expect(img.alt).toBe("Alt text")
106
+ expect(img.title).toBe("Image title")
107
+ })
108
+ })
109
+
110
+ describe("Table", () => {
111
+ it("creates table with header and rows", () => {
112
+ const table = new Table({
113
+ header: new TableRow({
114
+ cells: [
115
+ new TableCell({
116
+ isHeader: true,
117
+ children: [new Text({ value: "Col 1" })]
118
+ })
119
+ ]
120
+ }),
121
+ rows: [
122
+ new TableRow({
123
+ cells: [
124
+ new TableCell({
125
+ children: [new Text({ value: "Data" })]
126
+ })
127
+ ]
128
+ })
129
+ ]
130
+ })
131
+ expect(table._tag).toBe("Table")
132
+ expect(table.header?.cells).toHaveLength(1)
133
+ expect(table.rows).toHaveLength(1)
134
+ })
135
+ })
136
+
137
+ describe("List", () => {
138
+ it("creates unordered list", () => {
139
+ const result = Schema.decodeUnknownEither(List)({
140
+ _tag: "List",
141
+ ordered: false,
142
+ children: [
143
+ {
144
+ _tag: "ListItem",
145
+ children: [
146
+ {
147
+ _tag: "Paragraph",
148
+ children: [{ _tag: "Text", value: "Item 1" }]
149
+ }
150
+ ]
151
+ }
152
+ ]
153
+ })
154
+ expect(Either.isRight(result)).toBe(true)
155
+ if (Either.isRight(result)) {
156
+ expect(result.right.ordered).toBe(false)
157
+ expect(result.right.children).toHaveLength(1)
158
+ }
159
+ })
160
+
161
+ it("creates ordered list with start", () => {
162
+ const result = Schema.decodeUnknownEither(List)({
163
+ _tag: "List",
164
+ ordered: true,
165
+ start: 5,
166
+ children: []
167
+ })
168
+ expect(Either.isRight(result)).toBe(true)
169
+ if (Either.isRight(result)) {
170
+ expect(result.right.start).toBe(5)
171
+ }
172
+ })
173
+ })
174
+
175
+ describe("ListItem", () => {
176
+ it("creates list item with checked state", () => {
177
+ const result = Schema.decodeUnknownEither(ListItem)({
178
+ _tag: "ListItem",
179
+ checked: true,
180
+ children: [
181
+ {
182
+ _tag: "Paragraph",
183
+ children: [{ _tag: "Text", value: "Done" }]
184
+ }
185
+ ]
186
+ })
187
+ expect(Either.isRight(result)).toBe(true)
188
+ if (Either.isRight(result)) {
189
+ expect(result.right.checked).toBe(true)
190
+ }
191
+ })
192
+ })
193
+
194
+ describe("BlockQuote", () => {
195
+ it("creates block quote with children", () => {
196
+ const result = Schema.decodeUnknownEither(BlockQuote)({
197
+ _tag: "BlockQuote",
198
+ children: [
199
+ {
200
+ _tag: "Paragraph",
201
+ children: [{ _tag: "Text", value: "Quote" }]
202
+ }
203
+ ]
204
+ })
205
+ expect(Either.isRight(result)).toBe(true)
206
+ if (Either.isRight(result)) {
207
+ expect(result.right.children).toHaveLength(1)
208
+ }
209
+ })
210
+ })
211
+
212
+ describe("UnsupportedBlock", () => {
213
+ it("creates unsupported block from confluence", () => {
214
+ const block = new UnsupportedBlock({
215
+ rawHtml: "<ac:macro/>",
216
+ source: "confluence"
217
+ })
218
+ expect(block._tag).toBe("UnsupportedBlock")
219
+ expect(block.source).toBe("confluence")
220
+ })
221
+ })
222
+
223
+ describe("BlockNode union", () => {
224
+ it("decodes Heading variant", () => {
225
+ const result = Schema.decodeUnknownEither(BlockNode)({
226
+ _tag: "Heading",
227
+ level: 1,
228
+ children: []
229
+ })
230
+ expect(Either.isRight(result)).toBe(true)
231
+ })
232
+
233
+ it("decodes Paragraph variant", () => {
234
+ const result = Schema.decodeUnknownEither(BlockNode)({
235
+ _tag: "Paragraph",
236
+ children: [{ _tag: "Text", value: "text" }]
237
+ })
238
+ expect(Either.isRight(result)).toBe(true)
239
+ })
240
+
241
+ it("decodes List variant", () => {
242
+ const result = Schema.decodeUnknownEither(BlockNode)({
243
+ _tag: "List",
244
+ ordered: true,
245
+ children: []
246
+ })
247
+ expect(Either.isRight(result)).toBe(true)
248
+ })
249
+
250
+ it("decodes BlockQuote variant", () => {
251
+ const result = Schema.decodeUnknownEither(BlockNode)({
252
+ _tag: "BlockQuote",
253
+ children: []
254
+ })
255
+ expect(Either.isRight(result)).toBe(true)
256
+ })
257
+
258
+ it("rejects unknown tag", () => {
259
+ const result = Schema.decodeUnknownEither(BlockNode)({
260
+ _tag: "Unknown"
261
+ })
262
+ expect(Either.isLeft(result)).toBe(true)
263
+ })
264
+ })
265
+ })
@@ -0,0 +1,126 @@
1
+ import { describe, expect, it } from "@effect/vitest"
2
+ import * as Either from "effect/Either"
3
+ import * as Schema from "effect/Schema"
4
+ import { Heading } from "../../src/ast/BlockNode.js"
5
+ import { Document, isDocument, makeDocument } from "../../src/ast/Document.js"
6
+ import { Text } from "../../src/ast/InlineNode.js"
7
+
8
+ describe("Document", () => {
9
+ describe("Document schema", () => {
10
+ it("decodes valid document", () => {
11
+ const result = Schema.decodeUnknownEither(Document)({
12
+ children: [
13
+ {
14
+ _tag: "Heading",
15
+ level: 1,
16
+ children: [{ _tag: "Text", value: "Title" }]
17
+ },
18
+ {
19
+ _tag: "Paragraph",
20
+ children: [{ _tag: "Text", value: "Content" }]
21
+ }
22
+ ]
23
+ })
24
+ expect(Either.isRight(result)).toBe(true)
25
+ if (Either.isRight(result)) {
26
+ expect(result.right.version).toBe(1)
27
+ expect(result.right.children).toHaveLength(2)
28
+ }
29
+ })
30
+
31
+ it("decodes document with explicit version", () => {
32
+ const result = Schema.decodeUnknownEither(Document)({
33
+ version: 2,
34
+ children: []
35
+ })
36
+ expect(Either.isRight(result)).toBe(true)
37
+ if (Either.isRight(result)) {
38
+ expect(result.right.version).toBe(2)
39
+ }
40
+ })
41
+
42
+ it("decodes document with macro nodes", () => {
43
+ const result = Schema.decodeUnknownEither(Document)({
44
+ children: [
45
+ {
46
+ _tag: "InfoPanel",
47
+ panelType: "warning",
48
+ children: [
49
+ {
50
+ _tag: "Paragraph",
51
+ children: [{ _tag: "Text", value: "Warning!" }]
52
+ }
53
+ ]
54
+ }
55
+ ]
56
+ })
57
+ expect(Either.isRight(result)).toBe(true)
58
+ })
59
+
60
+ it("encodes document to plain object", () => {
61
+ const doc: Schema.Schema.Type<typeof Document> = {
62
+ version: 1,
63
+ children: [
64
+ new Heading({
65
+ level: 1,
66
+ children: [new Text({ value: "Hello" })]
67
+ })
68
+ ]
69
+ }
70
+ const result = Schema.encodeUnknownEither(Document)(doc)
71
+ expect(Either.isRight(result)).toBe(true)
72
+ })
73
+
74
+ it("rejects invalid children", () => {
75
+ const result = Schema.decodeUnknownEither(Document)({
76
+ children: [{ invalid: true }]
77
+ })
78
+ expect(Either.isLeft(result)).toBe(true)
79
+ })
80
+ })
81
+
82
+ describe("makeDocument", () => {
83
+ it("creates document with default version", () => {
84
+ const doc = makeDocument([
85
+ new Heading({
86
+ level: 1,
87
+ children: [new Text({ value: "Title" })]
88
+ })
89
+ ])
90
+ expect(doc.version).toBe(1)
91
+ expect(doc.children).toHaveLength(1)
92
+ })
93
+
94
+ it("creates empty document", () => {
95
+ const doc = makeDocument([])
96
+ expect(doc.children).toHaveLength(0)
97
+ })
98
+ })
99
+
100
+ describe("isDocument", () => {
101
+ it("returns true for valid document", () => {
102
+ const doc = makeDocument([])
103
+ expect(isDocument(doc)).toBe(true)
104
+ })
105
+
106
+ it("returns true for document-like object", () => {
107
+ expect(isDocument({ children: [] })).toBe(true)
108
+ })
109
+
110
+ it("returns false for null", () => {
111
+ expect(isDocument(null)).toBe(false)
112
+ })
113
+
114
+ it("returns false for non-object", () => {
115
+ expect(isDocument("string")).toBe(false)
116
+ })
117
+
118
+ it("returns false for object without children", () => {
119
+ expect(isDocument({ version: 1 })).toBe(false)
120
+ })
121
+
122
+ it("returns false for object with non-array children", () => {
123
+ expect(isDocument({ children: "not array" })).toBe(false)
124
+ })
125
+ })
126
+ })