Parting titles (as Hx).
This commit is contained in:
parent
d8faf1ff67
commit
aa30ceb903
8
.vscode/launch.json
vendored
8
.vscode/launch.json
vendored
@ -11,6 +11,14 @@
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"program": "${workspaceFolder}/dist/MakeMobiledoc.js",
|
||||
"outFiles": ["${workspaceFolder}/**/*.js"]
|
||||
},
|
||||
{
|
||||
"type": "pwa-node",
|
||||
"request": "launch",
|
||||
"name": "Markdown",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"program": "${workspaceFolder}/dist/Markdown.js",
|
||||
"outFiles": ["${workspaceFolder}/**/*.js"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
36
package-lock.json
generated
36
package-lock.json
generated
@ -18,10 +18,12 @@
|
||||
"markdown-it-github-preamble": "^1.0.0",
|
||||
"markdown-it-multimd-table": "^4.1.3",
|
||||
"markdown-yaml-metadata-parser": "^3.0.0",
|
||||
"mobiledoc-kit": "^0.14.0"
|
||||
"mobiledoc-kit": "^0.14.0",
|
||||
"yaml": "^2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.14.31",
|
||||
"@types/yaml": "^1.9.7",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.3.2"
|
||||
},
|
||||
@ -64,6 +66,16 @@
|
||||
"integrity": "sha512-x5W9s+8P4XteaxT/jKF0PSb7XEvo5VmqEWgsMlyeY4ZlLK8I6aH6g5TPPyDlLAep+GYf4kefb7HFyc7PAO3m+Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/yaml": {
|
||||
"version": "1.9.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz",
|
||||
"integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==",
|
||||
"deprecated": "This is a stub types definition. yaml provides its own type definitions, so you do not need this installed.",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yaml": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
@ -502,6 +514,14 @@
|
||||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
||||
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.1.tgz",
|
||||
"integrity": "sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw==",
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/yn": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
@ -548,6 +568,15 @@
|
||||
"integrity": "sha512-x5W9s+8P4XteaxT/jKF0PSb7XEvo5VmqEWgsMlyeY4ZlLK8I6aH6g5TPPyDlLAep+GYf4kefb7HFyc7PAO3m+Q==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/yaml": {
|
||||
"version": "1.9.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz",
|
||||
"integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yaml": "*"
|
||||
}
|
||||
},
|
||||
"arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
@ -888,6 +917,11 @@
|
||||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
||||
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
|
||||
},
|
||||
"yaml": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.1.tgz",
|
||||
"integrity": "sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw=="
|
||||
},
|
||||
"yn": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
|
@ -25,6 +25,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.14.31",
|
||||
"@types/yaml": "^1.9.7",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.3.2"
|
||||
},
|
||||
@ -38,6 +39,7 @@
|
||||
"markdown-it-github-preamble": "^1.0.0",
|
||||
"markdown-it-multimd-table": "^4.1.3",
|
||||
"markdown-yaml-metadata-parser": "^3.0.0",
|
||||
"mobiledoc-kit": "^0.14.0"
|
||||
"mobiledoc-kit": "^0.14.0",
|
||||
"yaml": "^2.1.1"
|
||||
}
|
||||
}
|
||||
|
115
src/Markdown.ts
115
src/Markdown.ts
@ -2,109 +2,22 @@
|
||||
* Load a file, parse it through markdonw-it and display its components
|
||||
*/
|
||||
|
||||
import fs from "fs";
|
||||
import MarkdownIt from "markdown-it";
|
||||
import Token from "markdown-it/lib/token";
|
||||
import metadataParser from "markdown-yaml-metadata-parser";
|
||||
import { Convertor } from "./convertor/Processors";
|
||||
const GhostAdminAPI = require("@tryghost/admin-api");
|
||||
|
||||
//const tabler = require("markdown-it-multimd-table");
|
||||
let convertor = new Convertor("./src/data/markdown-it-example.md");
|
||||
|
||||
interface Stack {
|
||||
tag: string;
|
||||
meta: any;
|
||||
}
|
||||
let mdoc: string = convertor.process();
|
||||
|
||||
interface Process {
|
||||
content: string;
|
||||
token: Token;
|
||||
}
|
||||
|
||||
function processBlock(buffer: string[], t: Token): Process {
|
||||
let tbuf: string[] = [];
|
||||
if (t.map != null)
|
||||
for (let i = t.map[0]; i < t.map[1]; i++) tbuf.push(buffer[i]);
|
||||
|
||||
return {
|
||||
content: tbuf.join("\n"),
|
||||
token: t,
|
||||
};
|
||||
}
|
||||
|
||||
let v: string = fs.readFileSync("./src/data/markdown-it-example.md", {
|
||||
encoding: "utf8",
|
||||
flag: "r",
|
||||
// Configure the client
|
||||
const api = new GhostAdminAPI({
|
||||
url: "http://localhost:2368",
|
||||
// Admin API key goes here
|
||||
key: "62ac6f5ab1479d0001082bd4:73341f843a5be78647c6f7e47d43d6cb09ec323df6d5706915df4685b3d46ce7",
|
||||
version: "v4.0",
|
||||
});
|
||||
|
||||
const parsed_md = metadataParser(v);
|
||||
|
||||
var src = MarkdownIt();
|
||||
//src.use(tabler);
|
||||
|
||||
//import markdownItGithubPreamble from "markdown-it-github-preamble";
|
||||
//src.use(markdownItGithubPreamble);
|
||||
let lines: string[] = parsed_md.content.split("\n");
|
||||
let tokens: Token[] = src.parse(parsed_md.content, { references: {} });
|
||||
let stack: Stack[] = [];
|
||||
|
||||
//let tableBuffer: string[] = [];
|
||||
let isTable = false;
|
||||
|
||||
//console.log(v);
|
||||
tokens.forEach((value: Token) => {
|
||||
let components: string[] = value.type.split("_");
|
||||
let action: string | undefined = components.pop();
|
||||
let name = components.join("_");
|
||||
switch (action) {
|
||||
case "open":
|
||||
if (name === "table") isTable = true;
|
||||
stack.push({ tag: value.tag, meta: value.meta } as never);
|
||||
if (isTable) {
|
||||
processBlock(lines, value);
|
||||
}
|
||||
break;
|
||||
case "close":
|
||||
if (name === "table") isTable = false;
|
||||
stack.pop();
|
||||
break;
|
||||
case "fence":
|
||||
processBlock(lines, value);
|
||||
break;
|
||||
case "inline":
|
||||
let t: string = "";
|
||||
let m: string = "";
|
||||
|
||||
stack.forEach((value) => {
|
||||
t += "-" + value.tag;
|
||||
m += ">" + JSON.stringify(value.meta);
|
||||
});
|
||||
if (isTable) {
|
||||
console.log("++++", JSON.stringify(value));
|
||||
} else {
|
||||
console.log(t, m, value.content);
|
||||
}
|
||||
break;
|
||||
// TODO: Make the 'FENCE' tag too!
|
||||
default:
|
||||
console.log("ERROR", components, action);
|
||||
//throw new Error("Con't know tag" + action);
|
||||
}
|
||||
/*
|
||||
console.log(
|
||||
value.level,
|
||||
"".padEnd(value.level, " "),
|
||||
JSON.stringify({
|
||||
type: value.type,
|
||||
//level: value.level,
|
||||
markup: value.markup,
|
||||
//meta: value.meta,
|
||||
content: value.content,
|
||||
block: value.block,
|
||||
//map: value.map,
|
||||
//tag: value.tag,
|
||||
//nesting: value.nesting,
|
||||
info: value.info,
|
||||
//children: value.children,
|
||||
})
|
||||
);
|
||||
*/
|
||||
});
|
||||
api.posts
|
||||
.add(JSON.parse(mdoc))
|
||||
.then((response: any) => console.log(JSON.stringify(response)))
|
||||
.catch((error: any) => console.error(error));
|
||||
|
0
src/Markdown2Mobiledoc.ts
Normal file
0
src/Markdown2Mobiledoc.ts
Normal file
179
src/convertor/Processors.ts
Normal file
179
src/convertor/Processors.ts
Normal file
@ -0,0 +1,179 @@
|
||||
import { PostNodeBuilder, Renderer } from "mobiledoc-kit";
|
||||
import fs from "fs";
|
||||
import MarkdownIt from "markdown-it";
|
||||
import Token from "markdown-it/lib/token";
|
||||
import metadataParser from "markdown-yaml-metadata-parser";
|
||||
|
||||
interface Stack {
|
||||
tag: string;
|
||||
meta: any;
|
||||
token: Token;
|
||||
}
|
||||
|
||||
const renderer: any = Renderer;
|
||||
|
||||
const predefinedBlocks = ["blockquote", "table", "bullet_list", "ordered_list"];
|
||||
|
||||
export class Convertor {
|
||||
markups: Record<string, any> = {};
|
||||
markers: Record<string, any> = {};
|
||||
sections: any[] = [];
|
||||
builder: any = new PostNodeBuilder();
|
||||
|
||||
// The markdown bits (preamble and content)
|
||||
//
|
||||
preamble: string = "";
|
||||
content: string = "";
|
||||
|
||||
// The line-by-line split of the markdown
|
||||
//
|
||||
lines: string[] = [];
|
||||
tokens: Token[] = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param filename the file name
|
||||
*/
|
||||
constructor(filename: string) {
|
||||
this.initialize(filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize/reset the convertor class.
|
||||
*
|
||||
* @param filename The file to be loaded
|
||||
*/
|
||||
public initialize(filename: string): Convertor {
|
||||
this.builder = new PostNodeBuilder();
|
||||
let content = fs.readFileSync(filename, {
|
||||
encoding: "utf8",
|
||||
flag: "r",
|
||||
});
|
||||
const parsed = metadataParser(content);
|
||||
this.preamble = parsed.preamble;
|
||||
this.content = parsed.content;
|
||||
|
||||
// Split the lines
|
||||
//
|
||||
this.lines = this.content.split("\n");
|
||||
|
||||
const markdownProcessor = MarkdownIt("commonmark");
|
||||
this.tokens = markdownProcessor.parse(this.content, { references: {} });
|
||||
return this;
|
||||
}
|
||||
|
||||
public process(): string {
|
||||
if (this.preamble === "" && this.content == "") {
|
||||
throw new Error(
|
||||
"Convertor not initialised. Please use initalize(...) first"
|
||||
);
|
||||
}
|
||||
|
||||
let stack: Stack[] = [];
|
||||
let blockNesting = 0;
|
||||
|
||||
// Loop through tokens
|
||||
this.tokens.forEach((value: Token) => {
|
||||
let components: string[] = value.type.split("_");
|
||||
let action: string | undefined = components.pop();
|
||||
let name = components.join("_");
|
||||
switch (action) {
|
||||
case "open":
|
||||
if (name in predefinedBlocks) blockNesting++;
|
||||
stack.push({
|
||||
tag: value.tag,
|
||||
meta: value.meta,
|
||||
token: value,
|
||||
} as never);
|
||||
break;
|
||||
case "close":
|
||||
if (name in predefinedBlocks) blockNesting--;
|
||||
stack.pop();
|
||||
break;
|
||||
case "fence":
|
||||
if (blockNesting == 0) {
|
||||
console.log("Process fence...");
|
||||
}
|
||||
break;
|
||||
case "inline":
|
||||
/*
|
||||
if (blockNesting == 0) {
|
||||
let t: string = "";
|
||||
let m: string = "";
|
||||
|
||||
stack.forEach((value) => {
|
||||
t += "-" + value.tag;
|
||||
m += ">" + JSON.stringify(value.meta);
|
||||
});
|
||||
console.log(t, m, value.content);
|
||||
}
|
||||
*/
|
||||
break;
|
||||
// TODO: Make the 'FENCE' tag too!
|
||||
default:
|
||||
console.log("ERROR", components, action);
|
||||
//throw new Error("Con't know tag" + action);
|
||||
}
|
||||
if (value.level == 0) {
|
||||
switch (name) {
|
||||
case "table":
|
||||
this.processBlock(value);
|
||||
break;
|
||||
case "heading":
|
||||
//this.sections.push(this.processHeader(value));
|
||||
break;
|
||||
default:
|
||||
this.processBlock(value);
|
||||
}
|
||||
} else if (blockNesting == 0 && action === "inline") {
|
||||
console.log(value.level, stack[0].token.type);
|
||||
switch (stack[0].token.type) {
|
||||
case "heading_open":
|
||||
this.sections.push(this.processHeader(stack, value));
|
||||
break;
|
||||
default:
|
||||
this.processInline(stack, value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Aggregate the sections into a new mobiledoc
|
||||
let post = this.builder.createPost(this.sections);
|
||||
let result = JSON.stringify({
|
||||
title: "A post",
|
||||
mobiledoc: `${JSON.stringify(renderer.render(post, "0.3.1"))}`,
|
||||
status: "draft",
|
||||
author: "laur.ivan@gmail.com",
|
||||
});
|
||||
console.log("BLOG ENTRY------------------------------------");
|
||||
console.log(result);
|
||||
console.log("BLOG ENTRY------------------------------------");
|
||||
return result;
|
||||
}
|
||||
|
||||
private processInline(stack: Stack[], t: Token) {
|
||||
console.log("*********************************************");
|
||||
console.log(JSON.stringify(t), stack.length);
|
||||
}
|
||||
|
||||
private processBlock(t: Token) {
|
||||
let tbuf: string[] = [];
|
||||
if (t.map != null)
|
||||
for (let i = t.map[0]; i < t.map[1]; i++) tbuf.push(this.lines[i]);
|
||||
//console.log("----------------------------------------------------");
|
||||
//console.log(JSON.stringify(t));
|
||||
return {
|
||||
content: tbuf.join("\n"),
|
||||
token: t,
|
||||
};
|
||||
}
|
||||
|
||||
private processHeader(stack: Stack[], t: Token): any {
|
||||
console.log("+++++++++++++++++++++++++++++++++++++++++++++");
|
||||
console.log(JSON.stringify(t));
|
||||
|
||||
let marker = this.builder.createMarker(t.content, []);
|
||||
return this.builder.createMarkupSection(stack[0].tag, [marker]);
|
||||
}
|
||||
}
|
@ -4,14 +4,14 @@
|
||||
"uuid": "41ced005-2d7c-4965-907c-0c87f5bfe1af",
|
||||
"title": "A post",
|
||||
"slug": "a-post",
|
||||
"mobiledoc": "{\"version\":\"0.3.1\",\"atoms\":[],\"cards\":[[\"markdown\",{\"markdown\":\"```js\\nlet value = 0\\n```\"}],[\"image\",{\"src\":\"http://localhost:2368/content/images/2022/06/ubuntu_black-orange_hex-1.png\",\"width\":758,\"height\":171,\"alt\":\"Ubuntu logo\"}]],\"markups\":[[\"strong\"]],\"sections\":[[1,\"p\",[[0,[0],0,\"Hi \"],[0,[],1,\" Bye\"]]],[10,0],[10,1],[1,\"p\",[]]],\"ghostVersion\":\"4.0\"}",
|
||||
"mobiledoc": "{\"version\":\"0.3.1\",\"atoms\":[],\"cards\":[[\"markdown\",{\"markdown\":\"```js\\nlet value = 0\\n```\"}],[\"image\",{\"src\":\"http://localhost:2368/content/images/2022/06/ubuntu_black-orange_hex-1.png\",\"width\":758,\"height\":171,\"alt\":\"Ubuntu logo\"}]],\"markups\":[[\"strong\"]],\"sections\":[[1,\"p\",[[0,[0],0,\"Hi \"],[0,[],1,\" Bye\"]]],[10,0],[10,1],[1,\"h2\",[[0,[],0,\"A title\"]]],[1,\"h3\",[[0,[],0,\"A second title\"]]]],\"ghostVersion\":\"4.0\"}",
|
||||
"comment_id": "62b81b265fb4ca000119c894",
|
||||
"feature_image": "http://localhost:2368/content/images/2022/06/dragonfly.jpg",
|
||||
"featured": false,
|
||||
"status": "published",
|
||||
"visibility": "public",
|
||||
"created_at": "2022-06-26T08:39:02.000Z",
|
||||
"updated_at": "2022-06-26T19:39:24.000Z",
|
||||
"updated_at": "2022-06-28T13:31:24.000Z",
|
||||
"published_at": "2022-06-26T08:39:23.000Z",
|
||||
"custom_excerpt": null,
|
||||
"codeinjection_head": null,
|
||||
@ -39,7 +39,7 @@
|
||||
"canonical_url": null,
|
||||
"accent_color": null,
|
||||
"created_at": "2022-05-31T12:27:26.000Z",
|
||||
"updated_at": "2022-06-26T19:39:24.000Z",
|
||||
"updated_at": "2022-06-28T13:31:24.000Z",
|
||||
"url": "http://localhost:2368/tag/news/"
|
||||
}
|
||||
],
|
||||
@ -61,9 +61,9 @@
|
||||
"meta_title": null,
|
||||
"meta_description": null,
|
||||
"tour": null,
|
||||
"last_seen": "2022-06-26T19:50:38.000Z",
|
||||
"last_seen": "2022-06-28T13:30:38.000Z",
|
||||
"created_at": "2022-05-31T12:27:26.000Z",
|
||||
"updated_at": "2022-06-26T19:50:38.000Z",
|
||||
"updated_at": "2022-06-28T13:30:38.000Z",
|
||||
"roles": [
|
||||
{
|
||||
"id": "629609ae8b281d00012eb297",
|
||||
@ -123,9 +123,9 @@
|
||||
"meta_title": null,
|
||||
"meta_description": null,
|
||||
"tour": null,
|
||||
"last_seen": "2022-06-26T19:50:38.000Z",
|
||||
"last_seen": "2022-06-28T13:30:38.000Z",
|
||||
"created_at": "2022-05-31T12:27:26.000Z",
|
||||
"updated_at": "2022-06-26T19:50:38.000Z",
|
||||
"updated_at": "2022-06-28T13:30:38.000Z",
|
||||
"roles": [
|
||||
{
|
||||
"id": "629609ae8b281d00012eb297",
|
||||
@ -157,12 +157,12 @@
|
||||
"canonical_url": null,
|
||||
"accent_color": null,
|
||||
"created_at": "2022-05-31T12:27:26.000Z",
|
||||
"updated_at": "2022-06-26T19:39:24.000Z",
|
||||
"updated_at": "2022-06-28T13:31:24.000Z",
|
||||
"url": "http://localhost:2368/tag/news/"
|
||||
},
|
||||
"email_segment": "all",
|
||||
"url": "http://localhost:2368/a-post/",
|
||||
"excerpt": "Hi Bye\n\nlet value = 0\n\n",
|
||||
"excerpt": "Hi Bye\n\nlet value = 0\n\n\n\n\nA title\n\n\nA second title",
|
||||
"og_image": null,
|
||||
"og_title": null,
|
||||
"og_description": null,
|
||||
|
Loading…
Reference in New Issue
Block a user