Skip to content

Commit

Permalink
fix: frontmatterHeader adds content direct to ADF instead of Markdown…
Browse files Browse the repository at this point in the history
… now
  • Loading branch information
andymac4182 committed May 1, 2023
1 parent 2c58c51 commit 1230878
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 146 deletions.
15 changes: 12 additions & 3 deletions packages/lib/src/ConniePageConfig.ts
@@ -1,6 +1,7 @@
import { JSONDocNode } from "@atlaskit/editor-json-transformer";
import { ConfluenceSettings } from "./Settings";
import { MarkdownFile } from "./adaptors";
import { parseMarkdownToADF } from "./MdToADF";

export type PageContentType = "page" | "blogpost";

Expand Down Expand Up @@ -132,7 +133,13 @@ export const conniePerPageConfig: ConfluencePerPageConfig = {
errors: [],
};
},
process: (yamlValue, markdownFile) => {
process: (
yamlValue,
markdownFile,
_alreadyParsed,
_settings,
adfContent
) => {
if (yamlValue && Array.isArray(yamlValue)) {
let frontmatterHeader =
"| Key | Value | \n | ----- | ----- |\n";
Expand All @@ -145,8 +152,10 @@ export const conniePerPageConfig: ConfluencePerPageConfig = {
frontmatterHeader += `| ${keyString} | ${valueString} |\n`;
}
}
markdownFile.contents =
frontmatterHeader + markdownFile.contents;

const newADF = parseMarkdownToADF(frontmatterHeader);

adfContent.content = [...newADF.content, ...adfContent.content];
}
return [];
},
Expand Down
17 changes: 8 additions & 9 deletions packages/lib/src/MdToADF.test.ts
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { expect, test } from "@jest/globals";
import { MarkdownFile } from "./adaptors";
import { MdToADF } from "./MdToADF";
import { convertMDtoADF } from "./MdToADF";
import { ConfluenceSettings } from "./Settings";

const markdownTestCases: MarkdownFile[] = [
Expand Down Expand Up @@ -199,16 +199,15 @@ const markdownTestCases: MarkdownFile[] = [
},
];
test.each(markdownTestCases)("parses $fileName", (markdown: MarkdownFile) => {
const mdToADF = new MdToADF();
const settings: ConfluenceSettings = {
confluenceBaseUrl: "",
confluenceParentId: "",
atlassianUserName: "",
atlassianApiToken: "",
folderToPublish: "",
contentRoot: "",
confluenceBaseUrl: "https://example.com",
confluenceParentId: "asdf",
atlassianUserName: "asdf@asdf.com",
atlassianApiToken: "asdfasdf",
folderToPublish: ".",
contentRoot: "./",
firstHeadingPageTitle: false,
};
const adfFile = mdToADF.convertMDtoADF(markdown, settings);
const adfFile = convertMDtoADF(markdown, settings);
expect(adfFile).toMatchSnapshot();
});
241 changes: 115 additions & 126 deletions packages/lib/src/MdToADF.ts
Expand Up @@ -14,144 +14,133 @@ import { ConfluenceSettings } from "./Settings";

const frontmatterRegex = /^\s*?---\n([\s\S]*?)\n---\s*/g;

export class MdToADF {
private transformer: MarkdownTransformer;
private serializer: JSONTransformer;
constructor() {
this.transformer = new MarkdownTransformer();
this.serializer = new JSONTransformer();
}

private parse(markdown: string) {
const prosenodes = this.transformer.parse(markdown);
const adfNodes = this.serializer.encode(prosenodes);
const nodes = this.processADF(adfNodes);
return nodes;
}

private processADF(adf: JSONDocNode): JSONDocNode {
const olivia = traverse(adf, {
text: (node, _parent) => {
if (
!(
node.marks &&
node.marks[0].type === "link" &&
node.marks[0].attrs &&
"href" in node.marks[0].attrs
)
) {
return;
}

if (
node.marks[0].attrs.href === "" ||
(!isSafeUrl(node.marks[0].attrs.href) &&
!(node.marks[0].attrs.href as string).startsWith(
"wikilink"
))
) {
node.marks[0].attrs.href = "#";
}

if (node.marks[0].attrs.href === node.text) {
node.type = "inlineCard";
node.attrs = { url: node.marks[0].attrs.href };
delete node.marks;
delete node.text;
}
const transformer = new MarkdownTransformer();
const serializer = new JSONTransformer();

export function parseMarkdownToADF(markdown: string) {
const prosenodes = transformer.parse(markdown);
const adfNodes = serializer.encode(prosenodes);
const nodes = processADF(adfNodes);
return nodes;
}

function processADF(adf: JSONDocNode): JSONDocNode {
const olivia = traverse(adf, {
text: (node, _parent) => {
if (
!(
node.marks &&
node.marks[0].type === "link" &&
node.marks[0].attrs &&
"href" in node.marks[0].attrs
)
) {
return;
}

if (
node.marks[0].attrs.href === "" ||
(!isSafeUrl(node.marks[0].attrs.href) &&
!(node.marks[0].attrs.href as string).startsWith(
"wikilink"
))
) {
node.marks[0].attrs.href = "#";
}

if (node.marks[0].attrs.href === node.text) {
node.type = "inlineCard";
node.attrs = { url: node.marks[0].attrs.href };
delete node.marks;
delete node.text;
}

return node;
},
table: (node, _parent) => {
if (
node.attrs &&
"isNumberColumnEnabled" in node.attrs &&
node.attrs["isNumberColumnEnabled"] === false
) {
delete node.attrs["isNumberColumnEnabled"];
}
return node;
},
tableRow: (node, _parent) => {
return node;
},
tableHeader: (node, _parent) => {
node.attrs = { colspan: 1, rowspan: 1, colwidth: [340] };
return node;
},
tableCell: (node, _parent) => {
node.attrs = { colspan: 1, rowspan: 1, colwidth: [340] };
return node;
},
orderedList: (node, _parent) => {
node.attrs = { order: 1 };
return node;
},
codeBlock: (node, _parent) => {
if (!node || !node.attrs) {
return;
}

if (Object.keys(node.attrs).length === 0) {
delete node.attrs;
return node;
},
table: (node, _parent) => {
if (
node.attrs &&
"isNumberColumnEnabled" in node.attrs &&
node.attrs["isNumberColumnEnabled"] === false
) {
delete node.attrs["isNumberColumnEnabled"];
}
return node;
},
tableRow: (node, _parent) => {
return node;
},
tableHeader: (node, _parent) => {
node.attrs = { colspan: 1, rowspan: 1, colwidth: [340] };
return node;
},
tableCell: (node, _parent) => {
node.attrs = { colspan: 1, rowspan: 1, colwidth: [340] };
return node;
},
orderedList: (node, _parent) => {
node.attrs = { order: 1 };
return node;
},
codeBlock: (node, _parent) => {
if (!node || !node.attrs) {
return;
}
}

if (Object.keys(node.attrs).length === 0) {
delete node.attrs;
return node;
}
const codeBlockLanguage = (node.attrs || {})?.language;

const codeBlockLanguage = (node.attrs || {})?.language;
if (codeBlockLanguage in MarkdownToConfluenceCodeBlockLanguageMap) {
node.attrs.language =
MarkdownToConfluenceCodeBlockLanguageMap[codeBlockLanguage];
}

if (
codeBlockLanguage in
MarkdownToConfluenceCodeBlockLanguageMap
) {
node.attrs.language =
MarkdownToConfluenceCodeBlockLanguageMap[
codeBlockLanguage
];
if (codeBlockLanguage === "adf") {
if (!node?.content?.at(0)?.text) {
return node;
}

if (codeBlockLanguage === "adf") {
if (!node?.content?.at(0)?.text) {
return node;
}
try {
const parsedAdf = JSON.parse(
node?.content?.at(0)?.text ??
JSON.stringify(
p("ADF missing from ADF Code Block.")
)
);
node = parsedAdf;
return node;
} catch (e) {
return node;
}
try {
const parsedAdf = JSON.parse(
node?.content?.at(0)?.text ??
JSON.stringify(
p("ADF missing from ADF Code Block.")
)
);
node = parsedAdf;
return node;
} catch (e) {
return node;
}
}

return node;
},
});

if (!olivia) {
throw new Error("Failed to traverse");
}
return node;
},
});

return olivia as JSONDocNode;
if (!olivia) {
throw new Error("Failed to traverse");
}

convertMDtoADF(
file: MarkdownFile,
settings: ConfluenceSettings
): LocalAdfFile {
file.contents = file.contents.replace(frontmatterRegex, "");
return olivia as JSONDocNode;
}

const adfContent = this.parse(file.contents);
export function convertMDtoADF(
file: MarkdownFile,
settings: ConfluenceSettings
): LocalAdfFile {
file.contents = file.contents.replace(frontmatterRegex, "");

const results = processConniePerPageConfig(file, settings, adfContent);
const adfContent = parseMarkdownToADF(file.contents);

return {
...file,
...results,
contents: adfContent,
};
}
const results = processConniePerPageConfig(file, settings, adfContent);

return {
...file,
...results,
contents: adfContent,
};
}
6 changes: 2 additions & 4 deletions packages/lib/src/TreeLocal.ts
@@ -1,13 +1,11 @@
import path from "path";
import { MarkdownFile } from "./adaptors";
import { MdToADF } from "./MdToADF";
import { convertMDtoADF } from "./MdToADF";
import { folderFile } from "./FolderFile";
import { JSONDocNode } from "@atlaskit/editor-json-transformer";
import { LocalAdfFileTreeNode } from "./Publisher";
import { ConfluenceSettings } from "./Settings";

const mdToADFConverter = new MdToADF();

const findCommonPath = (paths: string[]): string => {
const [firstPath, ...rest] = paths;
const commonPathParts = firstPath.split(path.sep);
Expand Down Expand Up @@ -39,7 +37,7 @@ const addFileToTree = (
const [folderName, ...remainingPath] = relativePath.split(path.sep);

if (remainingPath.length === 0) {
const adfFile = mdToADFConverter.convertMDtoADF(file, settings);
const adfFile = convertMDtoADF(file, settings);
treeNode.children.push({
...createTreeNode(folderName),
file: adfFile,
Expand Down
6 changes: 2 additions & 4 deletions packages/obsidian/src/AdfView.ts
Expand Up @@ -7,7 +7,7 @@ import {
} from "obsidian";
import {
ConfluenceUploadSettings,
MdToADF,
convertMDtoADF,
LoaderAdaptor,
} from "@markdown-confluence/lib";
import React from "react";
Expand All @@ -26,7 +26,6 @@ export default class AdfView extends ItemView {
fileName: string;
vault: Vault;
workspace: Workspace;
mdToAdf: MdToADF;
adaptor: LoaderAdaptor;

getViewType(): string {
Expand All @@ -52,7 +51,6 @@ export default class AdfView extends ItemView {
this.fileName = initialFileInfo.basename;
this.vault = this.app.vault;
this.workspace = this.app.workspace;
this.mdToAdf = new MdToADF();
this.adaptor = adaptor;
}

Expand All @@ -66,7 +64,7 @@ export default class AdfView extends ItemView {
}

const md = await this.adaptor.loadMarkdownFile(this.filePath);
const adf = this.mdToAdf.convertMDtoADF(md, this.settings).contents;
const adf = convertMDtoADF(md, this.settings).contents;
const renderADF = this.convertMediaFilesToLocalPath(adf);

const locale = "en";
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Expand Up @@ -18,6 +18,7 @@
"noUnusedParameters": false,
"noImplicitReturns": false /* Report error when not all code paths in function return a value. */,
"noFallthroughCasesInSwitch": false /* Report errors for fallthrough cases in switch statement. */,
"noImplicitThis": true,
"allowSyntheticDefaultImports":true,
"esModuleInterop":true,
"declaration": true,
Expand Down

0 comments on commit 1230878

Please sign in to comment.