@knpkv/confluence-to-markdown 0.6.0 → 0.7.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.
- package/CHANGELOG.md +39 -0
- package/LICENSE +21 -0
- package/README.md +22 -13
- package/dist/AdfPlaceholders.d.ts +42 -0
- package/dist/AdfPlaceholders.d.ts.map +1 -0
- package/dist/AdfPlaceholders.js +547 -0
- package/dist/AdfPlaceholders.js.map +1 -0
- package/dist/AdfSchemaValidator.d.ts +37 -0
- package/dist/AdfSchemaValidator.d.ts.map +1 -0
- package/dist/AdfSchemaValidator.js +37 -0
- package/dist/AdfSchemaValidator.js.map +1 -0
- package/dist/AdfWalker.d.ts +39 -0
- package/dist/AdfWalker.d.ts.map +1 -0
- package/dist/AdfWalker.js +527 -0
- package/dist/AdfWalker.js.map +1 -0
- package/dist/AtlaskitTransformers.d.ts +35 -0
- package/dist/AtlaskitTransformers.d.ts.map +1 -0
- package/dist/AtlaskitTransformers.js +48 -0
- package/dist/AtlaskitTransformers.js.map +1 -0
- package/dist/Brand.d.ts +6 -6
- package/dist/Brand.d.ts.map +1 -1
- package/dist/Brand.js +8 -6
- package/dist/Brand.js.map +1 -1
- package/dist/ConfluenceAuth.d.ts +4 -4
- package/dist/ConfluenceAuth.d.ts.map +1 -1
- package/dist/ConfluenceAuth.js +37 -39
- package/dist/ConfluenceAuth.js.map +1 -1
- package/dist/ConfluenceClient.d.ts +7 -17
- package/dist/ConfluenceClient.d.ts.map +1 -1
- package/dist/ConfluenceClient.js +81 -38
- package/dist/ConfluenceClient.js.map +1 -1
- package/dist/ConfluenceConfig.d.ts +3 -3
- package/dist/ConfluenceConfig.d.ts.map +1 -1
- package/dist/ConfluenceConfig.js +13 -11
- package/dist/ConfluenceConfig.js.map +1 -1
- package/dist/ConfluenceError.d.ts +68 -16
- package/dist/ConfluenceError.d.ts.map +1 -1
- package/dist/ConfluenceError.js +30 -1
- package/dist/ConfluenceError.js.map +1 -1
- package/dist/GitError.d.ts +5 -5
- package/dist/GitService.d.ts +11 -3
- package/dist/GitService.d.ts.map +1 -1
- package/dist/GitService.js +22 -27
- package/dist/GitService.js.map +1 -1
- package/dist/LocalFileSystem.d.ts +3 -3
- package/dist/LocalFileSystem.d.ts.map +1 -1
- package/dist/LocalFileSystem.js +6 -6
- package/dist/LocalFileSystem.js.map +1 -1
- package/dist/MarkdownConverter.d.ts +16 -65
- package/dist/MarkdownConverter.d.ts.map +1 -1
- package/dist/MarkdownConverter.js +64 -85
- package/dist/MarkdownConverter.js.map +1 -1
- package/dist/Schemas.d.ts +128 -141
- package/dist/Schemas.d.ts.map +1 -1
- package/dist/Schemas.js +21 -23
- package/dist/Schemas.js.map +1 -1
- package/dist/SyncEngine.d.ts +8 -5
- package/dist/SyncEngine.d.ts.map +1 -1
- package/dist/SyncEngine.js +189 -113
- package/dist/SyncEngine.js.map +1 -1
- package/dist/bin.js +23 -35
- package/dist/bin.js.map +1 -1
- package/dist/commands/auth.d.ts +2 -14
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +11 -16
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/clone.d.ts +4 -6
- package/dist/commands/clone.d.ts.map +1 -1
- package/dist/commands/clone.js +34 -32
- package/dist/commands/clone.js.map +1 -1
- package/dist/commands/delete.d.ts +2 -10
- package/dist/commands/delete.d.ts.map +1 -1
- package/dist/commands/delete.js +5 -4
- package/dist/commands/delete.js.map +1 -1
- package/dist/commands/errorHandler.d.ts +2 -1
- package/dist/commands/errorHandler.d.ts.map +1 -1
- package/dist/commands/errorHandler.js +22 -15
- package/dist/commands/errorHandler.js.map +1 -1
- package/dist/commands/fetch.d.ts +27 -0
- package/dist/commands/fetch.d.ts.map +1 -0
- package/dist/commands/fetch.js +48 -0
- package/dist/commands/fetch.js.map +1 -0
- package/dist/commands/git.d.ts +7 -10
- package/dist/commands/git.d.ts.map +1 -1
- package/dist/commands/git.js +6 -6
- package/dist/commands/git.js.map +1 -1
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +1 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/layers.d.ts +10 -9
- package/dist/commands/layers.d.ts.map +1 -1
- package/dist/commands/layers.js +41 -30
- package/dist/commands/layers.js.map +1 -1
- package/dist/commands/new.d.ts +2 -6
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +5 -4
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/pageInput.d.ts +19 -0
- package/dist/commands/pageInput.d.ts.map +1 -0
- package/dist/commands/pageInput.js +68 -0
- package/dist/commands/pageInput.js.map +1 -0
- package/dist/commands/root.d.ts +8 -0
- package/dist/commands/root.d.ts.map +1 -0
- package/dist/commands/root.js +29 -0
- package/dist/commands/root.js.map +1 -0
- package/dist/commands/sync.d.ts +6 -9
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +5 -6
- package/dist/commands/sync.js.map +1 -1
- package/dist/index.d.ts +3 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -13
- package/dist/index.js.map +1 -1
- package/dist/internal/NodeLayers.d.ts.map +1 -1
- package/dist/internal/NodeLayers.js +1 -2
- package/dist/internal/NodeLayers.js.map +1 -1
- package/dist/internal/adfMetadata.d.ts +30 -0
- package/dist/internal/adfMetadata.d.ts.map +1 -0
- package/dist/internal/adfMetadata.js +126 -0
- package/dist/internal/adfMetadata.js.map +1 -0
- package/dist/internal/cleanMarkdown.d.ts +5 -0
- package/dist/internal/cleanMarkdown.d.ts.map +1 -0
- package/dist/internal/cleanMarkdown.js +13 -0
- package/dist/internal/cleanMarkdown.js.map +1 -0
- package/dist/internal/frontmatter.d.ts.map +1 -1
- package/dist/internal/frontmatter.js +41 -8
- package/dist/internal/frontmatter.js.map +1 -1
- package/dist/internal/gitCommands.d.ts +9 -3
- package/dist/internal/gitCommands.d.ts.map +1 -1
- package/dist/internal/gitCommands.js +18 -9
- package/dist/internal/gitCommands.js.map +1 -1
- package/dist/internal/hashUtils.d.ts +1 -1
- package/dist/internal/hashUtils.d.ts.map +1 -1
- package/dist/internal/hashUtils.js +1 -1
- package/dist/internal/hashUtils.js.map +1 -1
- package/dist/internal/oauthServer.d.ts +10 -5
- package/dist/internal/oauthServer.d.ts.map +1 -1
- package/dist/internal/oauthServer.js +19 -40
- package/dist/internal/oauthServer.js.map +1 -1
- package/dist/internal/pathUtils.d.ts +1 -1
- package/dist/internal/pathUtils.d.ts.map +1 -1
- package/dist/internal/pathUtils.js +1 -1
- package/dist/internal/pathUtils.js.map +1 -1
- package/dist/internal/process.d.ts +15 -0
- package/dist/internal/process.d.ts.map +1 -0
- package/dist/internal/process.js +10 -0
- package/dist/internal/process.js.map +1 -0
- package/dist/internal/stdio.d.ts +6 -0
- package/dist/internal/stdio.d.ts.map +1 -0
- package/dist/internal/stdio.js +15 -0
- package/dist/internal/stdio.js.map +1 -0
- package/dist/internal/tokenStorage.d.ts +3 -13
- package/dist/internal/tokenStorage.d.ts.map +1 -1
- package/dist/internal/tokenStorage.js +26 -24
- package/dist/internal/tokenStorage.js.map +1 -1
- package/dist/internal/userCache.d.ts +1 -1
- package/dist/internal/userCache.d.ts.map +1 -1
- package/dist/internal/userCache.js +1 -1
- package/dist/internal/userCache.js.map +1 -1
- package/package.json +30 -30
- package/skills/confluence/SKILL.md +143 -0
- package/skills/confluence/agents/openai.yaml +4 -0
- package/src/AdfPlaceholders.ts +310 -13
- package/src/AdfSchemaValidator.ts +2 -4
- package/src/AdfWalker.ts +122 -42
- package/src/AtlaskitTransformers.ts +2 -4
- package/src/Brand.ts +11 -16
- package/src/ConfluenceAuth.ts +22 -30
- package/src/ConfluenceClient.ts +24 -20
- package/src/ConfluenceConfig.ts +14 -14
- package/src/GitService.ts +39 -49
- package/src/LocalFileSystem.ts +7 -9
- package/src/MarkdownConverter.ts +2 -4
- package/src/Schemas.ts +13 -12
- package/src/SyncEngine.ts +151 -53
- package/src/bin.ts +30 -56
- package/src/commands/auth.ts +21 -18
- package/src/commands/clone.ts +38 -37
- package/src/commands/delete.ts +5 -4
- package/src/commands/errorHandler.ts +25 -18
- package/src/commands/fetch.ts +90 -0
- package/src/commands/git.ts +6 -6
- package/src/commands/index.ts +1 -0
- package/src/commands/layers.ts +53 -33
- package/src/commands/new.ts +5 -4
- package/src/commands/pageInput.ts +103 -0
- package/src/commands/root.ts +59 -0
- package/src/commands/sync.ts +7 -6
- package/src/internal/NodeLayers.ts +1 -2
- package/src/internal/adfMetadata.ts +145 -0
- package/src/internal/cleanMarkdown.ts +15 -0
- package/src/internal/frontmatter.ts +45 -8
- package/src/internal/gitCommands.ts +23 -17
- package/src/internal/hashUtils.ts +2 -2
- package/src/internal/oauthServer.ts +84 -105
- package/src/internal/pathUtils.ts +1 -1
- package/src/internal/process.ts +15 -0
- package/src/internal/stdio.ts +22 -0
- package/src/internal/tokenStorage.ts +39 -29
- package/src/internal/userCache.ts +2 -2
- package/test/AdfPlaceholders.test.ts +213 -0
- package/test/AdfSchemaValidator.test.ts +6 -6
- package/test/AdfWalker.test.ts +167 -21
- package/test/AtlaskitTransformers.test.ts +4 -4
- package/test/Brand.test.ts +11 -11
- package/test/GitService.test.ts +6 -2
- package/test/MarkdownConverter.test.ts +12 -11
- package/test/RoundTrip.test.ts +258 -3
- package/test/Schemas.test.ts +40 -40
- package/test/adfMetadata.test.ts +110 -0
- package/test/cleanMarkdown.test.ts +36 -0
- package/test/commandHarness.test.ts +79 -0
- package/test/commandHarness.ts +147 -0
- package/test/fetch.test.ts +61 -0
- package/test/frontmatter.test.ts +41 -0
- package/test/integration.test.ts +569 -156
- package/test/layers.test.ts +12 -0
- package/test/oauthServer.test.ts +4 -5
- package/test/pageInput.test.ts +83 -0
- package/test/tokenStorage.test.ts +17 -17
- package/dist/SchemaConverterError.d.ts +0 -108
- package/dist/SchemaConverterError.d.ts.map +0 -1
- package/dist/SchemaConverterError.js +0 -84
- package/dist/SchemaConverterError.js.map +0 -1
- package/dist/ast/BlockNode.d.ts +0 -468
- package/dist/ast/BlockNode.d.ts.map +0 -1
- package/dist/ast/BlockNode.js +0 -319
- package/dist/ast/BlockNode.js.map +0 -1
- package/dist/ast/Document.d.ts +0 -244
- package/dist/ast/Document.d.ts.map +0 -1
- package/dist/ast/Document.js +0 -69
- package/dist/ast/Document.js.map +0 -1
- package/dist/ast/InlineNode.d.ts +0 -477
- package/dist/ast/InlineNode.d.ts.map +0 -1
- package/dist/ast/InlineNode.js +0 -263
- package/dist/ast/InlineNode.js.map +0 -1
- package/dist/ast/MacroNode.d.ts +0 -267
- package/dist/ast/MacroNode.d.ts.map +0 -1
- package/dist/ast/MacroNode.js +0 -164
- package/dist/ast/MacroNode.js.map +0 -1
- package/dist/ast/index.d.ts +0 -10
- package/dist/ast/index.d.ts.map +0 -1
- package/dist/ast/index.js +0 -14
- package/dist/ast/index.js.map +0 -1
- package/dist/parsers/ConfluenceParser.d.ts +0 -26
- package/dist/parsers/ConfluenceParser.d.ts.map +0 -1
- package/dist/parsers/ConfluenceParser.js +0 -792
- package/dist/parsers/ConfluenceParser.js.map +0 -1
- package/dist/parsers/MarkdownParser.d.ts +0 -26
- package/dist/parsers/MarkdownParser.d.ts.map +0 -1
- package/dist/parsers/MarkdownParser.js +0 -873
- package/dist/parsers/MarkdownParser.js.map +0 -1
- package/dist/parsers/index.d.ts +0 -8
- package/dist/parsers/index.d.ts.map +0 -1
- package/dist/parsers/index.js +0 -8
- package/dist/parsers/index.js.map +0 -1
- package/dist/parsers/preprocessing/ConfluencePreprocessing.d.ts +0 -23
- package/dist/parsers/preprocessing/ConfluencePreprocessing.d.ts.map +0 -1
- package/dist/parsers/preprocessing/ConfluencePreprocessing.js +0 -323
- package/dist/parsers/preprocessing/ConfluencePreprocessing.js.map +0 -1
- package/dist/parsers/preprocessing/index.d.ts +0 -7
- package/dist/parsers/preprocessing/index.d.ts.map +0 -1
- package/dist/parsers/preprocessing/index.js +0 -7
- package/dist/parsers/preprocessing/index.js.map +0 -1
- package/dist/schemas/ConfluenceSchema.d.ts +0 -21
- package/dist/schemas/ConfluenceSchema.d.ts.map +0 -1
- package/dist/schemas/ConfluenceSchema.js +0 -38
- package/dist/schemas/ConfluenceSchema.js.map +0 -1
- package/dist/schemas/ConversionSchema.d.ts +0 -35
- package/dist/schemas/ConversionSchema.d.ts.map +0 -1
- package/dist/schemas/ConversionSchema.js +0 -208
- package/dist/schemas/ConversionSchema.js.map +0 -1
- package/dist/schemas/MarkdownSchema.d.ts +0 -21
- package/dist/schemas/MarkdownSchema.d.ts.map +0 -1
- package/dist/schemas/MarkdownSchema.js +0 -38
- package/dist/schemas/MarkdownSchema.js.map +0 -1
- package/dist/schemas/hast/HastFromHtml.d.ts +0 -27
- package/dist/schemas/hast/HastFromHtml.d.ts.map +0 -1
- package/dist/schemas/hast/HastFromHtml.js +0 -107
- package/dist/schemas/hast/HastFromHtml.js.map +0 -1
- package/dist/schemas/hast/HastSchema.d.ts +0 -195
- package/dist/schemas/hast/HastSchema.d.ts.map +0 -1
- package/dist/schemas/hast/HastSchema.js +0 -183
- package/dist/schemas/hast/HastSchema.js.map +0 -1
- package/dist/schemas/hast/index.d.ts +0 -9
- package/dist/schemas/hast/index.d.ts.map +0 -1
- package/dist/schemas/hast/index.js +0 -3
- package/dist/schemas/hast/index.js.map +0 -1
- package/dist/schemas/index.d.ts +0 -14
- package/dist/schemas/index.d.ts.map +0 -1
- package/dist/schemas/index.js +0 -16
- package/dist/schemas/index.js.map +0 -1
- package/dist/schemas/mdast/MdastFromMarkdown.d.ts +0 -30
- package/dist/schemas/mdast/MdastFromMarkdown.d.ts.map +0 -1
- package/dist/schemas/mdast/MdastFromMarkdown.js +0 -79
- package/dist/schemas/mdast/MdastFromMarkdown.js.map +0 -1
- package/dist/schemas/mdast/MdastSchema.d.ts +0 -385
- package/dist/schemas/mdast/MdastSchema.d.ts.map +0 -1
- package/dist/schemas/mdast/MdastSchema.js +0 -266
- package/dist/schemas/mdast/MdastSchema.js.map +0 -1
- package/dist/schemas/mdast/index.d.ts +0 -10
- package/dist/schemas/mdast/index.d.ts.map +0 -1
- package/dist/schemas/mdast/index.js +0 -4
- package/dist/schemas/mdast/index.js.map +0 -1
- package/dist/schemas/mdast/mdastToString.d.ts +0 -13
- package/dist/schemas/mdast/mdastToString.d.ts.map +0 -1
- package/dist/schemas/mdast/mdastToString.js +0 -85
- package/dist/schemas/mdast/mdastToString.js.map +0 -1
- package/dist/schemas/nodes/block/BlockSchema.d.ts +0 -43
- package/dist/schemas/nodes/block/BlockSchema.d.ts.map +0 -1
- package/dist/schemas/nodes/block/BlockSchema.js +0 -634
- package/dist/schemas/nodes/block/BlockSchema.js.map +0 -1
- package/dist/schemas/nodes/block/index.d.ts +0 -7
- package/dist/schemas/nodes/block/index.d.ts.map +0 -1
- package/dist/schemas/nodes/block/index.js +0 -7
- package/dist/schemas/nodes/block/index.js.map +0 -1
- package/dist/schemas/nodes/index.d.ts +0 -9
- package/dist/schemas/nodes/index.d.ts.map +0 -1
- package/dist/schemas/nodes/index.js +0 -12
- package/dist/schemas/nodes/index.js.map +0 -1
- package/dist/schemas/nodes/inline/InlineSchema.d.ts +0 -48
- package/dist/schemas/nodes/inline/InlineSchema.d.ts.map +0 -1
- package/dist/schemas/nodes/inline/InlineSchema.js +0 -436
- package/dist/schemas/nodes/inline/InlineSchema.js.map +0 -1
- package/dist/schemas/nodes/inline/index.d.ts +0 -7
- package/dist/schemas/nodes/inline/index.d.ts.map +0 -1
- package/dist/schemas/nodes/inline/index.js +0 -7
- package/dist/schemas/nodes/inline/index.js.map +0 -1
- package/dist/schemas/nodes/macro/MacroSchema.d.ts +0 -27
- package/dist/schemas/nodes/macro/MacroSchema.d.ts.map +0 -1
- package/dist/schemas/nodes/macro/MacroSchema.js +0 -162
- package/dist/schemas/nodes/macro/MacroSchema.js.map +0 -1
- package/dist/schemas/nodes/macro/index.d.ts +0 -7
- package/dist/schemas/nodes/macro/index.d.ts.map +0 -1
- package/dist/schemas/nodes/macro/index.js +0 -7
- package/dist/schemas/nodes/macro/index.js.map +0 -1
- package/dist/schemas/preprocessing/ConfluencePreprocessor.d.ts +0 -53
- package/dist/schemas/preprocessing/ConfluencePreprocessor.d.ts.map +0 -1
- package/dist/schemas/preprocessing/ConfluencePreprocessor.js +0 -349
- package/dist/schemas/preprocessing/ConfluencePreprocessor.js.map +0 -1
- package/dist/schemas/preprocessing/index.d.ts +0 -8
- package/dist/schemas/preprocessing/index.d.ts.map +0 -1
- package/dist/schemas/preprocessing/index.js +0 -2
- package/dist/schemas/preprocessing/index.js.map +0 -1
- package/dist/serializers/ConfluenceSerializer.d.ts +0 -30
- package/dist/serializers/ConfluenceSerializer.d.ts.map +0 -1
- package/dist/serializers/ConfluenceSerializer.js +0 -551
- package/dist/serializers/ConfluenceSerializer.js.map +0 -1
- package/dist/serializers/MarkdownSerializer.d.ts +0 -34
- package/dist/serializers/MarkdownSerializer.d.ts.map +0 -1
- package/dist/serializers/MarkdownSerializer.js +0 -355
- package/dist/serializers/MarkdownSerializer.js.map +0 -1
- package/dist/serializers/index.d.ts +0 -8
- package/dist/serializers/index.d.ts.map +0 -1
- package/dist/serializers/index.js +0 -8
- package/dist/serializers/index.js.map +0 -1
|
@@ -3,6 +3,7 @@ import { revertPlaceholders } from "../src/AdfPlaceholders.js"
|
|
|
3
3
|
|
|
4
4
|
const docOf = (content: ReadonlyArray<unknown>) => ({ version: 1, type: "doc", content })
|
|
5
5
|
const para = (text: string) => ({ type: "paragraph", content: [{ type: "text", text }] })
|
|
6
|
+
const b64 = (value: unknown): string => Buffer.from(JSON.stringify(value)).toString("base64")
|
|
6
7
|
|
|
7
8
|
describe("revertPlaceholders", () => {
|
|
8
9
|
it("rewrites a status span placeholder into a status node", () => {
|
|
@@ -31,6 +32,53 @@ describe("revertPlaceholders", () => {
|
|
|
31
32
|
})
|
|
32
33
|
})
|
|
33
34
|
|
|
35
|
+
it("rewrites native TOC syntax into a Confluence core extension node", () => {
|
|
36
|
+
const out = revertPlaceholders(docOf([para("[[toc]]")])) as {
|
|
37
|
+
content: Array<{ type: string; attrs?: Record<string, unknown> }>
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
expect(out.content[0]).toEqual({
|
|
41
|
+
type: "extension",
|
|
42
|
+
attrs: {
|
|
43
|
+
extensionKey: "toc",
|
|
44
|
+
extensionType: "com.atlassian.confluence.macro.core"
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it("rewrites native TOC syntax with levels into macro parameters", () => {
|
|
50
|
+
const out = revertPlaceholders(docOf([para("[[toc:min=2,max=4]]")])) as {
|
|
51
|
+
content: Array<{ type: string; attrs?: Record<string, unknown> }>
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
expect(out.content[0]).toEqual({
|
|
55
|
+
type: "extension",
|
|
56
|
+
attrs: {
|
|
57
|
+
extensionKey: "toc",
|
|
58
|
+
extensionType: "com.atlassian.confluence.macro.core",
|
|
59
|
+
parameters: {
|
|
60
|
+
macroParams: {
|
|
61
|
+
minLevel: { value: "2" },
|
|
62
|
+
maxLevel: { value: "4" }
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it("leaves invalid or code-marked native TOC syntax as text", () => {
|
|
70
|
+
const invalid = revertPlaceholders(docOf([para("[[toc:min=0]]")])) as {
|
|
71
|
+
content: Array<{ type: string; content?: ReadonlyArray<unknown> }>
|
|
72
|
+
}
|
|
73
|
+
const quoted = revertPlaceholders(docOf([{
|
|
74
|
+
type: "paragraph",
|
|
75
|
+
content: [{ type: "text", text: "[[toc]]", marks: [{ type: "code" }] }]
|
|
76
|
+
}])) as { content: Array<{ type: string; content?: ReadonlyArray<unknown> }> }
|
|
77
|
+
|
|
78
|
+
expect(invalid.content[0]!.type).toBe("paragraph")
|
|
79
|
+
expect(quoted.content[0]!.type).toBe("paragraph")
|
|
80
|
+
})
|
|
81
|
+
|
|
34
82
|
it("rewrites status and extension placeholders inside table cells", () => {
|
|
35
83
|
const cell = (text: string) => ({
|
|
36
84
|
type: "tableCell",
|
|
@@ -85,6 +133,67 @@ describe("revertPlaceholders", () => {
|
|
|
85
133
|
})
|
|
86
134
|
})
|
|
87
135
|
|
|
136
|
+
it("rewrites fallback inline formatting HTML into native marks", () => {
|
|
137
|
+
const out = revertPlaceholders(
|
|
138
|
+
docOf([para(
|
|
139
|
+
`Plain <u>underline</u>, H<sub>2</sub>O, x<sup>2</sup>, ` +
|
|
140
|
+
`<span style="color:#ff5630">Colored text</span>, ` +
|
|
141
|
+
`<span style="background-color:#f8e6a0">highlighted text</span>.`
|
|
142
|
+
)])
|
|
143
|
+
) as {
|
|
144
|
+
content: Array<{
|
|
145
|
+
content: Array<{ type: string; text?: string; marks?: ReadonlyArray<{ type: string; attrs?: unknown }> }>
|
|
146
|
+
}>
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const inlineContent = out.content[0]!.content
|
|
150
|
+
expect(inlineContent).toContainEqual({
|
|
151
|
+
type: "text",
|
|
152
|
+
text: "underline",
|
|
153
|
+
marks: [{ type: "underline" }]
|
|
154
|
+
})
|
|
155
|
+
expect(inlineContent).toContainEqual({
|
|
156
|
+
type: "text",
|
|
157
|
+
text: "2",
|
|
158
|
+
marks: [{ type: "subsup", attrs: { type: "sub" } }]
|
|
159
|
+
})
|
|
160
|
+
expect(inlineContent).toContainEqual({
|
|
161
|
+
type: "text",
|
|
162
|
+
text: "2",
|
|
163
|
+
marks: [{ type: "subsup", attrs: { type: "sup" } }]
|
|
164
|
+
})
|
|
165
|
+
expect(inlineContent).toContainEqual({
|
|
166
|
+
type: "text",
|
|
167
|
+
text: "Colored text",
|
|
168
|
+
marks: [{ type: "textColor", attrs: { color: "#ff5630" } }]
|
|
169
|
+
})
|
|
170
|
+
expect(inlineContent).toContainEqual({
|
|
171
|
+
type: "text",
|
|
172
|
+
text: "highlighted text",
|
|
173
|
+
marks: [{ type: "backgroundColor", attrs: { color: "#f8e6a0" } }]
|
|
174
|
+
})
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it("rewrites inlineCard placeholders into native smart-link nodes", () => {
|
|
178
|
+
const attrs = { url: "https://www.atlassian.com" }
|
|
179
|
+
const out = revertPlaceholders(
|
|
180
|
+
docOf([para(`Inline smart link: <!-- adf:inlineCard attrs=${b64(attrs)} -->.`)])
|
|
181
|
+
) as { content: Array<{ content: Array<{ type: string; attrs?: Record<string, unknown> }> }> }
|
|
182
|
+
|
|
183
|
+
expect(out.content[0]!.content[1]).toEqual({ type: "inlineCard", attrs })
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
it("rewrites encoded date and emoji placeholders into native inline nodes", () => {
|
|
187
|
+
const date = { type: "date", attrs: { timestamp: "1782259200000" } }
|
|
188
|
+
const emoji = { type: "emoji", attrs: { shortName: ":white_check_mark:", text: "✅" } }
|
|
189
|
+
const out = revertPlaceholders(
|
|
190
|
+
docOf([para(`Example <!-- adf:date node=${b64(date)} --> <!-- adf:emoji node=${b64(emoji)} -->`)])
|
|
191
|
+
) as { content: Array<{ content: Array<unknown> }> }
|
|
192
|
+
|
|
193
|
+
expect(out.content[0]!.content).toContainEqual(date)
|
|
194
|
+
expect(out.content[0]!.content).toContainEqual(emoji)
|
|
195
|
+
})
|
|
196
|
+
|
|
88
197
|
it("restores the full attrs (parameters included) from an attrs blob", () => {
|
|
89
198
|
const attrs = {
|
|
90
199
|
extensionKey: "toc",
|
|
@@ -135,6 +244,110 @@ describe("revertPlaceholders", () => {
|
|
|
135
244
|
expect(out.content[1]).toEqual(para("after"))
|
|
136
245
|
})
|
|
137
246
|
|
|
247
|
+
it("re-attaches the blocks between panel markers as a panel body", () => {
|
|
248
|
+
const attrs = { panelType: "warning" }
|
|
249
|
+
const blob = Buffer.from(JSON.stringify(attrs)).toString("base64")
|
|
250
|
+
const out = revertPlaceholders(
|
|
251
|
+
docOf([
|
|
252
|
+
para(`<!-- adf:panel type=warning attrs=${blob} -->`),
|
|
253
|
+
para("panel body"),
|
|
254
|
+
para(`<!-- adf:/panel -->`),
|
|
255
|
+
para("after")
|
|
256
|
+
])
|
|
257
|
+
) as { content: Array<{ type: string; attrs?: Record<string, unknown>; content?: ReadonlyArray<unknown> }> }
|
|
258
|
+
|
|
259
|
+
expect(out.content).toHaveLength(2)
|
|
260
|
+
expect(out.content[0]).toEqual({
|
|
261
|
+
type: "panel",
|
|
262
|
+
attrs,
|
|
263
|
+
content: [para("panel body")]
|
|
264
|
+
})
|
|
265
|
+
expect(out.content[1]).toEqual(para("after"))
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
it("re-attaches paragraph-level marks from paragraph markers", () => {
|
|
269
|
+
const marks = [{ type: "alignment", attrs: { align: "center" } }]
|
|
270
|
+
const out = revertPlaceholders(
|
|
271
|
+
docOf([
|
|
272
|
+
para(`<!-- adf:paragraph marks=${b64(marks)} -->`),
|
|
273
|
+
para("Centered paragraph for alignment validation."),
|
|
274
|
+
para(`<!-- adf:/paragraph -->`)
|
|
275
|
+
])
|
|
276
|
+
) as { content: Array<{ type: string; marks?: unknown; content?: ReadonlyArray<unknown> }> }
|
|
277
|
+
|
|
278
|
+
expect(out.content).toEqual([{
|
|
279
|
+
type: "paragraph",
|
|
280
|
+
marks,
|
|
281
|
+
content: [{ type: "text", text: "Centered paragraph for alignment validation." }]
|
|
282
|
+
}])
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
it("restores encoded native block nodes", () => {
|
|
286
|
+
const taskList = {
|
|
287
|
+
type: "taskList",
|
|
288
|
+
attrs: { localId: "tasks-1" },
|
|
289
|
+
content: [{
|
|
290
|
+
type: "taskItem",
|
|
291
|
+
attrs: { localId: "task-1", state: "DONE" },
|
|
292
|
+
content: [{ type: "text", text: "Existing primitive coverage reviewed" }]
|
|
293
|
+
}]
|
|
294
|
+
}
|
|
295
|
+
const decisionList = {
|
|
296
|
+
type: "decisionList",
|
|
297
|
+
attrs: { localId: "decisions-1" },
|
|
298
|
+
content: [{
|
|
299
|
+
type: "decisionItem",
|
|
300
|
+
attrs: { localId: "decision-1", state: "DECIDED" },
|
|
301
|
+
content: [{ type: "text", text: "Decide whether to maintain a separate asset for advanced macros." }]
|
|
302
|
+
}]
|
|
303
|
+
}
|
|
304
|
+
const expand = {
|
|
305
|
+
type: "expand",
|
|
306
|
+
attrs: { title: "Expandable supplementary content" },
|
|
307
|
+
content: [para("This section can be expanded.")]
|
|
308
|
+
}
|
|
309
|
+
const table = {
|
|
310
|
+
type: "table",
|
|
311
|
+
content: [{ type: "tableRow", content: [{ type: "tableCell", content: [para("Date")] }] }]
|
|
312
|
+
}
|
|
313
|
+
const layoutSection = {
|
|
314
|
+
type: "layoutSection",
|
|
315
|
+
content: [{ type: "layoutColumn", attrs: { width: 50 }, content: [para("Left column")] }]
|
|
316
|
+
}
|
|
317
|
+
const blockCard = { type: "blockCard", attrs: { url: "https://www.atlassian.com/software/confluence" } }
|
|
318
|
+
const embedCard = {
|
|
319
|
+
type: "embedCard",
|
|
320
|
+
attrs: { url: "https://www.atlassian.com/software/confluence", layout: "center" }
|
|
321
|
+
}
|
|
322
|
+
const out = revertPlaceholders(
|
|
323
|
+
docOf([
|
|
324
|
+
para(`<!-- adf:taskList node=${b64(taskList)} -->`),
|
|
325
|
+
para("[x] Existing primitive coverage reviewed"),
|
|
326
|
+
para("<!-- adf:/taskList -->"),
|
|
327
|
+
para(`<!-- adf:decisionList node=${b64(decisionList)} -->`),
|
|
328
|
+
para("This page will act as the baseline integration test asset for editor primitive coverage."),
|
|
329
|
+
para("<!-- adf:/decisionList -->"),
|
|
330
|
+
para(`<!-- adf:expand node=${b64(expand)} -->`),
|
|
331
|
+
para("This section can be expanded."),
|
|
332
|
+
para("<!-- adf:/expand -->"),
|
|
333
|
+
para(`<!-- adf:table node=${b64(table)} -->`),
|
|
334
|
+
para("| Date |"),
|
|
335
|
+
para("<!-- adf:/table -->"),
|
|
336
|
+
para(`<!-- adf:layoutSection node=${b64(layoutSection)} -->`),
|
|
337
|
+
para("Left column"),
|
|
338
|
+
para("<!-- adf:/layoutSection -->"),
|
|
339
|
+
para(`<!-- adf:blockCard node=${b64(blockCard)} -->`),
|
|
340
|
+
para("https://www.atlassian.com/software/confluence"),
|
|
341
|
+
para("<!-- adf:/blockCard -->"),
|
|
342
|
+
para(`<!-- adf:embedCard node=${b64(embedCard)} -->`),
|
|
343
|
+
para("https://www.atlassian.com/software/confluence"),
|
|
344
|
+
para("<!-- adf:/embedCard -->")
|
|
345
|
+
])
|
|
346
|
+
) as { content: Array<unknown> }
|
|
347
|
+
|
|
348
|
+
expect(out.content).toEqual([taskList, decisionList, expand, table, layoutSection, blockCard, embedCard])
|
|
349
|
+
})
|
|
350
|
+
|
|
138
351
|
it("reverts an extension marker nested inside a bodiedExtension body", () => {
|
|
139
352
|
const out = revertPlaceholders(
|
|
140
353
|
docOf([
|
|
@@ -23,12 +23,12 @@ describe("AdfSchemaValidator", () => {
|
|
|
23
23
|
type: "doc",
|
|
24
24
|
content: [{ type: "paragraph", content: [{ type: "text", text: 42 }] }]
|
|
25
25
|
}
|
|
26
|
-
const result = yield* Effect.
|
|
27
|
-
expect(result._tag).toBe("
|
|
28
|
-
if (result._tag === "
|
|
29
|
-
expect(result.
|
|
30
|
-
expect(result.
|
|
31
|
-
expect(result.
|
|
26
|
+
const result = yield* Effect.result(v.check(doc, "incoming"))
|
|
27
|
+
expect(result._tag).toBe("Failure")
|
|
28
|
+
if (result._tag === "Failure") {
|
|
29
|
+
expect(result.failure._tag).toBe("AdfSchemaError")
|
|
30
|
+
expect(result.failure.direction).toBe("incoming")
|
|
31
|
+
expect(result.failure.issues.length).toBeGreaterThan(0)
|
|
32
32
|
}
|
|
33
33
|
}).pipe(Effect.provide(AdfSchemaValidatorLayer)))
|
|
34
34
|
})
|
package/test/AdfWalker.test.ts
CHANGED
|
@@ -4,9 +4,18 @@ import { walk } from "../src/AdfWalker.js"
|
|
|
4
4
|
|
|
5
5
|
const doc = (content: ReadonlyArray<unknown>): DocNode => ({ version: 1, type: "doc", content } as unknown as DocNode)
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const stableStringify = (v: unknown): string => {
|
|
8
|
+
if (Array.isArray(v)) return `[${v.map(stableStringify).join(",")}]`
|
|
9
|
+
if (v !== null && typeof v === "object") {
|
|
10
|
+
return `{${
|
|
11
|
+
Object.entries(v as Record<string, unknown>)
|
|
12
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
13
|
+
.map(([k, value]) => `${JSON.stringify(k)}:${stableStringify(value)}`)
|
|
14
|
+
.join(",")
|
|
15
|
+
}}`
|
|
16
|
+
}
|
|
17
|
+
return JSON.stringify(v) ?? "null"
|
|
18
|
+
}
|
|
10
19
|
|
|
11
20
|
describe("AdfWalker", () => {
|
|
12
21
|
it("emits a heading at the right level", () => {
|
|
@@ -159,34 +168,57 @@ describe("AdfWalker", () => {
|
|
|
159
168
|
expect(r.markdown).toContain("| 1 | 2 |")
|
|
160
169
|
})
|
|
161
170
|
|
|
162
|
-
it("renders a panel as a
|
|
171
|
+
it("renders a panel as a Confluence-preserving placeholder", () => {
|
|
163
172
|
const r = walk(doc([{
|
|
164
173
|
type: "panel",
|
|
165
174
|
attrs: { panelType: "warning" },
|
|
166
175
|
content: [{ type: "paragraph", content: [{ type: "text", text: "be careful" }] }]
|
|
167
176
|
}]))
|
|
168
|
-
expect(r.markdown).toContain(
|
|
177
|
+
expect(r.markdown).toContain(
|
|
178
|
+
`<!-- adf:panel type=warning attrs=${stableStringify({ panelType: "warning" })} -->`
|
|
179
|
+
)
|
|
169
180
|
expect(r.markdown).toContain("be careful")
|
|
181
|
+
expect(r.markdown).toContain("<!-- adf:/panel -->")
|
|
170
182
|
})
|
|
171
183
|
|
|
172
184
|
it("renders task lists with checkbox state", () => {
|
|
173
|
-
const
|
|
185
|
+
const node = {
|
|
174
186
|
type: "taskList",
|
|
187
|
+
attrs: { localId: "tasks-1" },
|
|
175
188
|
content: [
|
|
176
189
|
{
|
|
177
190
|
type: "taskItem",
|
|
178
|
-
attrs: { state: "DONE" },
|
|
191
|
+
attrs: { localId: "task-1", state: "DONE" },
|
|
179
192
|
content: [{ type: "text", text: "done" }]
|
|
180
193
|
},
|
|
181
194
|
{
|
|
182
195
|
type: "taskItem",
|
|
183
|
-
attrs: { state: "TODO" },
|
|
196
|
+
attrs: { localId: "task-2", state: "TODO" },
|
|
184
197
|
content: [{ type: "text", text: "todo" }]
|
|
185
198
|
}
|
|
186
199
|
]
|
|
187
|
-
}
|
|
200
|
+
}
|
|
201
|
+
const r = walk(doc([node]))
|
|
202
|
+
expect(r.markdown).toContain(`<!-- adf:taskList node=${stableStringify(node)} -->`)
|
|
188
203
|
expect(r.markdown).toContain("- [x] done")
|
|
189
204
|
expect(r.markdown).toContain("- [ ] todo")
|
|
205
|
+
expect(r.markdown).toContain("<!-- adf:/taskList -->")
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
it("wraps decision lists so they survive push as native decisions", () => {
|
|
209
|
+
const node = {
|
|
210
|
+
type: "decisionList",
|
|
211
|
+
attrs: { localId: "decisions-1" },
|
|
212
|
+
content: [{
|
|
213
|
+
type: "decisionItem",
|
|
214
|
+
attrs: { localId: "decision-1", state: "DECIDED" },
|
|
215
|
+
content: [{ type: "text", text: "decide" }]
|
|
216
|
+
}]
|
|
217
|
+
}
|
|
218
|
+
const r = walk(doc([node]))
|
|
219
|
+
expect(r.markdown).toContain(`<!-- adf:decisionList node=${stableStringify(node)} -->`)
|
|
220
|
+
expect(r.markdown).toContain("- 🔘 decide")
|
|
221
|
+
expect(r.markdown).toContain("<!-- adf:/decisionList -->")
|
|
190
222
|
})
|
|
191
223
|
|
|
192
224
|
it("renders every child of a mediaGroup", () => {
|
|
@@ -237,23 +269,51 @@ describe("AdfWalker", () => {
|
|
|
237
269
|
expect(r.markdown).not.toContain("confluence-mention")
|
|
238
270
|
})
|
|
239
271
|
|
|
240
|
-
it("
|
|
272
|
+
it("renders a representable TOC extension as readable native syntax", () => {
|
|
273
|
+
const r = walk(doc([{
|
|
274
|
+
type: "extension",
|
|
275
|
+
attrs: {
|
|
276
|
+
extensionKey: "toc",
|
|
277
|
+
extensionType: "com.atlassian.confluence.macro.core"
|
|
278
|
+
}
|
|
279
|
+
}]))
|
|
280
|
+
expect(r.markdown).toContain("[[toc]]")
|
|
281
|
+
expect(r.warnings).not.toContainEqual(
|
|
282
|
+
expect.objectContaining({ _tag: "UnsupportedExtension", extensionKey: "toc" })
|
|
283
|
+
)
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
it("renders representable TOC levels in readable native syntax", () => {
|
|
241
287
|
const r = walk(doc([{
|
|
242
288
|
type: "extension",
|
|
243
289
|
attrs: {
|
|
244
290
|
extensionType: "com.atlassian.confluence.macro.core",
|
|
245
291
|
extensionKey: "toc",
|
|
246
|
-
parameters: {
|
|
292
|
+
parameters: {
|
|
293
|
+
macroParams: {
|
|
294
|
+
minLevel: { value: "2" },
|
|
295
|
+
maxLevel: { value: "4" }
|
|
296
|
+
}
|
|
297
|
+
}
|
|
247
298
|
}
|
|
248
299
|
}]))
|
|
249
|
-
|
|
300
|
+
expect(r.markdown).toContain("[[toc:min=2,max=4]]")
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
it("falls back to a generic placeholder when TOC attrs are not fully representable", () => {
|
|
304
|
+
const rawAttrs = {
|
|
250
305
|
extensionKey: "toc",
|
|
251
306
|
extensionType: "com.atlassian.confluence.macro.core",
|
|
307
|
+
layout: "default",
|
|
308
|
+
localId: "abc-123",
|
|
252
309
|
parameters: { macroParams: { maxLevel: { value: "3" } } }
|
|
253
|
-
}
|
|
310
|
+
}
|
|
311
|
+
const r = walk(doc([{ type: "extension", attrs: rawAttrs }]))
|
|
312
|
+
const attrs = stableStringify(rawAttrs)
|
|
254
313
|
expect(r.markdown).toContain(
|
|
255
314
|
`<!-- adf:extension key=toc type=com.atlassian.confluence.macro.core attrs=${attrs} -->`
|
|
256
315
|
)
|
|
316
|
+
expect(r.markdown).not.toContain("[[toc")
|
|
257
317
|
expect(
|
|
258
318
|
r.warnings.some((w) =>
|
|
259
319
|
w._tag === "UnsupportedExtension" && w.extensionKey === "toc" && w.nodeType === "extension"
|
|
@@ -261,6 +321,27 @@ describe("AdfWalker", () => {
|
|
|
261
321
|
).toBe(true)
|
|
262
322
|
})
|
|
263
323
|
|
|
324
|
+
it("falls back to a generic placeholder for Confluence TOC macroMetadata", () => {
|
|
325
|
+
const rawAttrs = {
|
|
326
|
+
extensionKey: "toc",
|
|
327
|
+
extensionType: "com.atlassian.confluence.macro.core",
|
|
328
|
+
layout: "default",
|
|
329
|
+
parameters: {
|
|
330
|
+
macroMetadata: {
|
|
331
|
+
schemaVersion: { value: "1" },
|
|
332
|
+
title: "Table of Contents"
|
|
333
|
+
},
|
|
334
|
+
macroParams: {}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const r = walk(doc([{ type: "extension", attrs: rawAttrs }]))
|
|
338
|
+
const attrs = stableStringify(rawAttrs)
|
|
339
|
+
expect(r.markdown).toContain(
|
|
340
|
+
`<!-- adf:extension key=toc type=com.atlassian.confluence.macro.core attrs=${attrs} -->`
|
|
341
|
+
)
|
|
342
|
+
expect(r.markdown).not.toContain("[[toc")
|
|
343
|
+
})
|
|
344
|
+
|
|
264
345
|
it("emits the same attrs blob regardless of source key order", () => {
|
|
265
346
|
const a = walk(doc([{ type: "extension", attrs: { extensionKey: "toc", extensionType: "t" } }]))
|
|
266
347
|
const b = walk(doc([{ type: "extension", attrs: { extensionType: "t", extensionKey: "toc" } }]))
|
|
@@ -283,8 +364,8 @@ describe("AdfWalker", () => {
|
|
|
283
364
|
content: [{ type: "paragraph", content: [{ type: "text", text: "body" }] }]
|
|
284
365
|
}
|
|
285
366
|
]))
|
|
286
|
-
const inlineAttrs =
|
|
287
|
-
const bodiedAttrs =
|
|
367
|
+
const inlineAttrs = stableStringify({ extensionKey: "jira-issue", extensionType: "com.example" })
|
|
368
|
+
const bodiedAttrs = stableStringify({ extensionKey: "details", extensionType: "com.example" })
|
|
288
369
|
expect(r.markdown).toContain(
|
|
289
370
|
`<!-- adf:inlineExtension key=jira-issue type=com.example attrs=${inlineAttrs} -->`
|
|
290
371
|
)
|
|
@@ -325,7 +406,7 @@ describe("AdfWalker", () => {
|
|
|
325
406
|
}]
|
|
326
407
|
}]))
|
|
327
408
|
expect(r.markdown).not.toContain("adf:/bodiedExtension")
|
|
328
|
-
expect(r.markdown).not.toContain("
|
|
409
|
+
expect(r.markdown).not.toContain("\n\nbody\n\n")
|
|
329
410
|
expect(r.markdown).toContain("<!-- adf:bodiedExtension key=details type=com.example")
|
|
330
411
|
})
|
|
331
412
|
|
|
@@ -362,6 +443,42 @@ describe("AdfWalker", () => {
|
|
|
362
443
|
expect(r.markdown).toContain("\n_Figure 1_")
|
|
363
444
|
})
|
|
364
445
|
|
|
446
|
+
it("renders layout sections and columns as visible markdown content", () => {
|
|
447
|
+
const r = walk(doc([{
|
|
448
|
+
type: "layoutSection",
|
|
449
|
+
content: [
|
|
450
|
+
{
|
|
451
|
+
type: "layoutColumn",
|
|
452
|
+
attrs: { width: 50 },
|
|
453
|
+
content: [{ type: "paragraph", content: [{ type: "text", text: "left" }] }]
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
type: "layoutColumn",
|
|
457
|
+
attrs: { width: 50 },
|
|
458
|
+
content: [{ type: "paragraph", content: [{ type: "text", text: "right" }] }]
|
|
459
|
+
}
|
|
460
|
+
]
|
|
461
|
+
}]))
|
|
462
|
+
expect(r.markdown).toContain("left\n\nright")
|
|
463
|
+
expect(r.warnings.some((w) => w._tag === "UnsupportedNode" && w.nodeType === "layoutSection")).toBe(false)
|
|
464
|
+
expect(r.warnings.some((w) => w._tag === "UnsupportedNode" && w.nodeType === "layoutColumn")).toBe(false)
|
|
465
|
+
})
|
|
466
|
+
|
|
467
|
+
it("renders block and embed smart cards from direct and nested urls", () => {
|
|
468
|
+
const blockCard = { type: "blockCard", attrs: { url: "https://x.test/block" } }
|
|
469
|
+
const embedCard = { type: "embedCard", attrs: { data: { url: "https://x.test/embed" } } }
|
|
470
|
+
const r = walk(doc([
|
|
471
|
+
blockCard,
|
|
472
|
+
embedCard
|
|
473
|
+
]))
|
|
474
|
+
expect(r.markdown).toContain(`<!-- adf:blockCard node=${stableStringify(blockCard)} -->`)
|
|
475
|
+
expect(r.markdown).toContain("<https://x.test/block>")
|
|
476
|
+
expect(r.markdown).toContain(`<!-- adf:embedCard node=${stableStringify(embedCard)} -->`)
|
|
477
|
+
expect(r.markdown).toContain("<https://x.test/embed>")
|
|
478
|
+
expect(r.warnings.some((w) => w._tag === "UnsupportedNode" && w.nodeType === "blockCard")).toBe(false)
|
|
479
|
+
expect(r.warnings.some((w) => w._tag === "UnsupportedNode" && w.nodeType === "embedCard")).toBe(false)
|
|
480
|
+
})
|
|
481
|
+
|
|
365
482
|
it("backslash-escapes nestedExpand titles inside table cells (inline HTML context)", () => {
|
|
366
483
|
const r = walk(doc([{
|
|
367
484
|
type: "table",
|
|
@@ -386,7 +503,8 @@ describe("AdfWalker", () => {
|
|
|
386
503
|
attrs: { title: `v2 *beta* <a href="x">` },
|
|
387
504
|
content: [{ type: "paragraph", content: [{ type: "text", text: "inner" }] }]
|
|
388
505
|
}]))
|
|
389
|
-
expect(r.markdown).toContain(
|
|
506
|
+
expect(r.markdown).toContain(`<!-- adf:expand node=`)
|
|
507
|
+
expect(r.markdown).toContain(`v2 *beta* <a href="x">`)
|
|
390
508
|
expect(r.markdown).not.toContain("\\*beta\\*")
|
|
391
509
|
})
|
|
392
510
|
|
|
@@ -465,13 +583,39 @@ describe("AdfWalker", () => {
|
|
|
465
583
|
type: "paragraph",
|
|
466
584
|
content: [
|
|
467
585
|
{ type: "text", text: "before " },
|
|
468
|
-
{ type: "inlineCard", attrs: { data: {
|
|
586
|
+
{ type: "inlineCard", attrs: { data: { title: "hidden" } } },
|
|
469
587
|
{ type: "text", text: " after" }
|
|
470
588
|
]
|
|
471
589
|
}]))
|
|
472
590
|
expect(r.warnings.some((w) => w._tag === "UnsupportedNode" && w.nodeType === "inlineCard")).toBe(true)
|
|
473
591
|
})
|
|
474
592
|
|
|
593
|
+
it("renders inline cards from nested data urls", () => {
|
|
594
|
+
const r = walk(doc([{
|
|
595
|
+
type: "paragraph",
|
|
596
|
+
content: [
|
|
597
|
+
{ type: "text", text: "see " },
|
|
598
|
+
{ type: "inlineCard", attrs: { data: { url: "https://x.test/inline" } } }
|
|
599
|
+
]
|
|
600
|
+
}]))
|
|
601
|
+
expect(r.markdown).toContain(
|
|
602
|
+
`see <!-- adf:inlineCard attrs=${stableStringify({ data: { url: "https://x.test/inline" } })} -->`
|
|
603
|
+
)
|
|
604
|
+
expect(r.warnings.some((w) => w._tag === "UnsupportedNode" && w.nodeType === "inlineCard")).toBe(false)
|
|
605
|
+
})
|
|
606
|
+
|
|
607
|
+
it("wraps paragraph-level marks so alignment and indentation survive push", () => {
|
|
608
|
+
const marks = [{ type: "alignment", attrs: { align: "center" } }]
|
|
609
|
+
const r = walk(doc([{
|
|
610
|
+
type: "paragraph",
|
|
611
|
+
marks,
|
|
612
|
+
content: [{ type: "text", text: "centered" }]
|
|
613
|
+
}]))
|
|
614
|
+
expect(r.markdown).toContain(`<!-- adf:paragraph marks=${stableStringify(marks)} -->`)
|
|
615
|
+
expect(r.markdown).toContain("centered")
|
|
616
|
+
expect(r.markdown).toContain("<!-- adf:/paragraph -->")
|
|
617
|
+
})
|
|
618
|
+
|
|
475
619
|
it("does not double-wrap an em-marked caption", () => {
|
|
476
620
|
const r = walk(doc([{
|
|
477
621
|
type: "mediaSingle",
|
|
@@ -505,7 +649,7 @@ describe("AdfWalker", () => {
|
|
|
505
649
|
expect(r.markdown).toContain("_orphan_")
|
|
506
650
|
})
|
|
507
651
|
|
|
508
|
-
it("
|
|
652
|
+
it("preserves note and success panel types", () => {
|
|
509
653
|
const r = walk(doc([
|
|
510
654
|
{
|
|
511
655
|
type: "panel",
|
|
@@ -518,8 +662,10 @@ describe("AdfWalker", () => {
|
|
|
518
662
|
content: [{ type: "paragraph", content: [{ type: "text", text: "s" }] }]
|
|
519
663
|
}
|
|
520
664
|
]))
|
|
521
|
-
expect(r.markdown).toContain("
|
|
522
|
-
expect(r.markdown).toContain(
|
|
665
|
+
expect(r.markdown).toContain(`<!-- adf:panel type=note attrs=${stableStringify({ panelType: "note" })} -->`)
|
|
666
|
+
expect(r.markdown).toContain(
|
|
667
|
+
`<!-- adf:panel type=success attrs=${stableStringify({ panelType: "success" })} -->`
|
|
668
|
+
)
|
|
523
669
|
})
|
|
524
670
|
|
|
525
671
|
it("ends output with exactly one newline", () => {
|
|
@@ -14,12 +14,12 @@ describe("AtlaskitTransformers", () => {
|
|
|
14
14
|
it.effect("surfaces synchronous throws as AtlaskitTransformersError", () =>
|
|
15
15
|
Effect.gen(function*() {
|
|
16
16
|
const t = yield* AtlaskitTransformers
|
|
17
|
-
const result = yield* Effect.
|
|
17
|
+
const result = yield* Effect.result(t.use(() => {
|
|
18
18
|
throw new Error("boom")
|
|
19
19
|
}))
|
|
20
|
-
expect(result._tag).toBe("
|
|
21
|
-
if (result._tag === "
|
|
22
|
-
expect(result.
|
|
20
|
+
expect(result._tag).toBe("Failure")
|
|
21
|
+
if (result._tag === "Failure") {
|
|
22
|
+
expect(result.failure._tag).toBe("AtlaskitTransformersError")
|
|
23
23
|
}
|
|
24
24
|
}).pipe(Effect.provide(AtlaskitTransformersLayer)))
|
|
25
25
|
})
|
package/test/Brand.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "@effect/vitest"
|
|
2
|
-
import * as
|
|
2
|
+
import * as Result from "effect/Result"
|
|
3
3
|
import * as Schema from "effect/Schema"
|
|
4
4
|
import { ContentHash, PageId, PageIdSchema, SpaceKey, SpaceKeySchema } from "../src/Brand.js"
|
|
5
5
|
|
|
@@ -17,13 +17,13 @@ describe("Brand", () => {
|
|
|
17
17
|
|
|
18
18
|
describe("PageIdSchema", () => {
|
|
19
19
|
it("decodes valid page IDs", () => {
|
|
20
|
-
const result = Schema.
|
|
21
|
-
expect(
|
|
20
|
+
const result = Schema.decodeUnknownResult(PageIdSchema)("123456")
|
|
21
|
+
expect(Result.isSuccess(result)).toBe(true)
|
|
22
22
|
})
|
|
23
23
|
|
|
24
24
|
it("rejects empty strings", () => {
|
|
25
|
-
const result = Schema.
|
|
26
|
-
expect(
|
|
25
|
+
const result = Schema.decodeUnknownResult(PageIdSchema)("")
|
|
26
|
+
expect(Result.isFailure(result)).toBe(true)
|
|
27
27
|
})
|
|
28
28
|
})
|
|
29
29
|
|
|
@@ -40,18 +40,18 @@ describe("Brand", () => {
|
|
|
40
40
|
|
|
41
41
|
describe("SpaceKeySchema", () => {
|
|
42
42
|
it("decodes uppercase alphanumeric keys", () => {
|
|
43
|
-
const result = Schema.
|
|
44
|
-
expect(
|
|
43
|
+
const result = Schema.decodeUnknownResult(SpaceKeySchema)("MYSPACE123")
|
|
44
|
+
expect(Result.isSuccess(result)).toBe(true)
|
|
45
45
|
})
|
|
46
46
|
|
|
47
47
|
it("rejects lowercase keys", () => {
|
|
48
|
-
const result = Schema.
|
|
49
|
-
expect(
|
|
48
|
+
const result = Schema.decodeUnknownResult(SpaceKeySchema)("myspace")
|
|
49
|
+
expect(Result.isFailure(result)).toBe(true)
|
|
50
50
|
})
|
|
51
51
|
|
|
52
52
|
it("rejects keys with special characters", () => {
|
|
53
|
-
const result = Schema.
|
|
54
|
-
expect(
|
|
53
|
+
const result = Schema.decodeUnknownResult(SpaceKeySchema)("MY-SPACE")
|
|
54
|
+
expect(Result.isFailure(result)).toBe(true)
|
|
55
55
|
})
|
|
56
56
|
})
|
|
57
57
|
|
package/test/GitService.test.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { NodeServices } from "@effect/platform-node"
|
|
1
2
|
import { describe, expect, it } from "@effect/vitest"
|
|
2
3
|
import * as Effect from "effect/Effect"
|
|
4
|
+
import * as Layer from "effect/Layer"
|
|
3
5
|
import { GitService, layer as GitServiceLayer } from "../src/GitService.js"
|
|
4
6
|
import { getConflictedFiles, GIT_LOG_FORMAT, parseGitLog, parseGitStatus } from "../src/internal/gitCommands.js"
|
|
5
7
|
|
|
@@ -7,6 +9,8 @@ import { getConflictedFiles, GIT_LOG_FORMAT, parseGitLog, parseGitStatus } from
|
|
|
7
9
|
* Tests for git parsing utilities and GitService.
|
|
8
10
|
*/
|
|
9
11
|
describe("GitService", () => {
|
|
12
|
+
const TestLayer = Layer.provideMerge(GitServiceLayer, NodeServices.layer)
|
|
13
|
+
|
|
10
14
|
describe("parseGitStatus", () => {
|
|
11
15
|
it("parses empty status", () => {
|
|
12
16
|
const entries = parseGitStatus("")
|
|
@@ -197,13 +201,13 @@ M normal.ts`
|
|
|
197
201
|
const git = yield* GitService
|
|
198
202
|
const version = yield* git.validateGit()
|
|
199
203
|
expect(version).toContain("git version")
|
|
200
|
-
}).pipe(Effect.provide(
|
|
204
|
+
}).pipe(Effect.provide(TestLayer)))
|
|
201
205
|
|
|
202
206
|
it.effect("isInitialized returns boolean", () =>
|
|
203
207
|
Effect.gen(function*() {
|
|
204
208
|
const git = yield* GitService
|
|
205
209
|
const initialized = yield* git.isInitialized()
|
|
206
210
|
expect(typeof initialized).toBe("boolean")
|
|
207
|
-
}).pipe(Effect.provide(
|
|
211
|
+
}).pipe(Effect.provide(TestLayer)))
|
|
208
212
|
})
|
|
209
213
|
})
|