Added resources drafts.
This commit is contained in:
parent
be2467d2c8
commit
4e95c02b6f
20
.env
Normal file
20
.env
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Flag to push posts to the ghost instance
|
||||||
|
#
|
||||||
|
PUSH_POSTS=true
|
||||||
|
|
||||||
|
# Download remote/internet-hosted images?
|
||||||
|
#
|
||||||
|
DOWNLOAD_IMAGES=false
|
||||||
|
|
||||||
|
# Base URL
|
||||||
|
# Final URL should be: https://www.laurivan.com/
|
||||||
|
BASE_URL="http://localhost:2368"
|
||||||
|
|
||||||
|
# Ghost - related variables
|
||||||
|
#
|
||||||
|
API_KEY="62ac6f5ab1479d0001082bd4:73341f843a5be78647c6f7e47d43d6cb09ec323df6d5706915df4685b3d46ce7"
|
||||||
|
API_VERSION="v4.0"
|
||||||
|
AUTHOR_EMAIL=laur.ivan@gmail.com
|
||||||
|
|
||||||
|
# Location of head/hero images
|
||||||
|
HEAD_IMAGE_PATH="src/data/images/headers/"
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
.idea
|
.idea
|
||||||
|
data
|
||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
temp
|
temp
|
||||||
|
1
.prettierignore
Normal file
1
.prettierignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
.env
|
5
.prettierrc
Normal file
5
.prettierrc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"semi": true
|
||||||
|
}
|
12
.vscode/settings.json
vendored
Normal file
12
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"editor.formatOnPaste": true,
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"html.format.enable": true,
|
||||||
|
"json.format.enable": true,
|
||||||
|
"javascript.format.enable": true,
|
||||||
|
"typescript.format.enable": true,
|
||||||
|
"css.format.enable": true,
|
||||||
|
"less.format.enable": true,
|
||||||
|
"scss.format.enable": true,
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
}
|
14
package-lock.json
generated
14
package-lock.json
generated
@ -12,6 +12,7 @@
|
|||||||
"@tryghost/admin-api": "^1.13.0",
|
"@tryghost/admin-api": "^1.13.0",
|
||||||
"@types/markdown-it": "^12.2.3",
|
"@types/markdown-it": "^12.2.3",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
|
"dotenv": "^16.0.1",
|
||||||
"fs": "^0.0.1-security",
|
"fs": "^0.0.1-security",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"markdown-it": "^13.0.1",
|
"markdown-it": "^13.0.1",
|
||||||
@ -154,6 +155,14 @@
|
|||||||
"node": ">=0.3.1"
|
"node": ">=0.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dotenv": {
|
||||||
|
"version": "16.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz",
|
||||||
|
"integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ecdsa-sig-formatter": {
|
"node_modules/ecdsa-sig-formatter": {
|
||||||
"version": "1.0.11",
|
"version": "1.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||||
@ -643,6 +652,11 @@
|
|||||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"dotenv": {
|
||||||
|
"version": "16.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz",
|
||||||
|
"integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ=="
|
||||||
|
},
|
||||||
"ecdsa-sig-formatter": {
|
"ecdsa-sig-formatter": {
|
||||||
"version": "1.0.11",
|
"version": "1.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
"@tryghost/admin-api": "^1.13.0",
|
"@tryghost/admin-api": "^1.13.0",
|
||||||
"@types/markdown-it": "^12.2.3",
|
"@types/markdown-it": "^12.2.3",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
|
"dotenv": "^16.0.1",
|
||||||
"fs": "^0.0.1-security",
|
"fs": "^0.0.1-security",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"markdown-it": "^13.0.1",
|
"markdown-it": "^13.0.1",
|
||||||
|
@ -19,10 +19,6 @@ switch (command) {
|
|||||||
.browse()
|
.browse()
|
||||||
.then((response: any) => console.log(JSON.stringify(response)))
|
.then((response: any) => console.log(JSON.stringify(response)))
|
||||||
.catch((error: any) => console.error(error));
|
.catch((error: any) => console.error(error));
|
||||||
api.images
|
|
||||||
.browse()
|
|
||||||
.then((response: any) => console.log(JSON.stringify(response)))
|
|
||||||
.catch((error: any) => console.error(error));
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
const post = fs.readFileSync("./src/data/draftpost.json", {
|
const post = fs.readFileSync("./src/data/draftpost.json", {
|
||||||
|
@ -1,33 +1,35 @@
|
|||||||
/**
|
/**
|
||||||
* Load a file, parse it through markdonw-it and display its components
|
* Load a file, parse it through markdonw-it and display its components
|
||||||
*/
|
*/
|
||||||
|
import * as dotenv from "dotenv";
|
||||||
import { Convertor } from "./convertor/Processors";
|
//import { ImageProcessor } from "./convertor/ImageProcessor";
|
||||||
|
import { BlockConvertor as Convertor } from "./convertor/BlockConvertor";
|
||||||
const GhostAdminAPI = require("@tryghost/admin-api");
|
const GhostAdminAPI = require("@tryghost/admin-api");
|
||||||
|
|
||||||
|
// Init config
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
// Configure the client
|
// Configure the client
|
||||||
const api = new GhostAdminAPI({
|
const api = new GhostAdminAPI({
|
||||||
url: "http://localhost:2368",
|
url: process.env.BASE_URL,
|
||||||
// Admin API key goes here
|
// Admin API key goes here
|
||||||
key: "62ac6f5ab1479d0001082bd4:73341f843a5be78647c6f7e47d43d6cb09ec323df6d5706915df4685b3d46ce7",
|
key: process.env.API_KEY,
|
||||||
version: "v4.0",
|
version: process.env.API_VERSION,
|
||||||
});
|
|
||||||
let convertor = new Convertor("./src/data/markdown-it-example.md");
|
|
||||||
convertor
|
|
||||||
.processImages(api, "./temp")
|
|
||||||
.then(() => {
|
|
||||||
console.log("ok");
|
|
||||||
})
|
|
||||||
.catch((r) => {
|
|
||||||
console.log(r);
|
|
||||||
});
|
});
|
||||||
|
let convertor = new Convertor(
|
||||||
|
"./src/data/blog/2019-10-31-ie-11-angular-compatibility.md"
|
||||||
|
);
|
||||||
|
//let imageProcessor = new ImageProcessor();
|
||||||
|
|
||||||
let mdoc: string = ""; //convertor.process();
|
async function main() {
|
||||||
|
//await imageProcessor.processImages(convertor, api, "./temp");
|
||||||
let creation = false;
|
await convertor.process(api);
|
||||||
|
|
||||||
if (creation) {
|
|
||||||
api.posts
|
|
||||||
.add(JSON.parse(mdoc))
|
|
||||||
.then((response: any) => console.log(JSON.stringify(response)))
|
|
||||||
.catch((error: any) => console.error(error));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
.then(() => {
|
||||||
|
console.log("OK");
|
||||||
|
})
|
||||||
|
.catch((r: any) => {
|
||||||
|
throw new Error(r);
|
||||||
|
});
|
||||||
|
147
src/convertor/BlockConvertor.ts
Normal file
147
src/convertor/BlockConvertor.ts
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
import { PostNodeBuilder, Renderer } from "mobiledoc-kit";
|
||||||
|
import fs from "fs";
|
||||||
|
import metadataParser from "markdown-yaml-metadata-parser";
|
||||||
|
import { Convertor } from "./Convertor";
|
||||||
|
//import { StackedImage } from "./ImageProcessor";
|
||||||
|
import path from "node:path";
|
||||||
|
import { downloadImagefromURL, uploadToGhost } from "./images";
|
||||||
|
|
||||||
|
const renderer: any = Renderer;
|
||||||
|
|
||||||
|
export class BlockConvertor implements Convertor {
|
||||||
|
builder: any = new PostNodeBuilder();
|
||||||
|
filename: string;
|
||||||
|
// The markdown bits (preamble and content)
|
||||||
|
//
|
||||||
|
metadata: any;
|
||||||
|
content = "";
|
||||||
|
featureImage: string | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param filename the file name
|
||||||
|
*/
|
||||||
|
constructor(filename: string) {
|
||||||
|
this.filename = filename;
|
||||||
|
this.initialize(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
setFeatureImage(url: string): void {
|
||||||
|
this.featureImage = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize/reset the convertor class.
|
||||||
|
*
|
||||||
|
* @param filename The file to be loaded
|
||||||
|
*/
|
||||||
|
public initialize(filename: string): BlockConvertor {
|
||||||
|
this.builder = new PostNodeBuilder();
|
||||||
|
let content = fs.readFileSync(filename, {
|
||||||
|
encoding: "utf8",
|
||||||
|
flag: "r",
|
||||||
|
});
|
||||||
|
const parsed = metadataParser(content);
|
||||||
|
this.metadata = parsed.metadata;
|
||||||
|
this.content = parsed.content;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async process(api: any) {
|
||||||
|
await this.processImages(api, "./temp");
|
||||||
|
let markdownSection = this.builder.createCardSection("markdown", {
|
||||||
|
markdown: this.content,
|
||||||
|
});
|
||||||
|
|
||||||
|
let post = this.builder.createPost([markdownSection]);
|
||||||
|
|
||||||
|
let result = JSON.stringify({
|
||||||
|
title: this.metadata.title,
|
||||||
|
slug: this.metadata.slug,
|
||||||
|
mobiledoc: `${JSON.stringify(renderer.render(post, "0.3.1"))}`,
|
||||||
|
status:
|
||||||
|
"draft" in this.metadata
|
||||||
|
? this.metadata["draft"]
|
||||||
|
? "draft"
|
||||||
|
: "published"
|
||||||
|
: "draft",
|
||||||
|
visibility: "public",
|
||||||
|
created_at: this.metadata["date"],
|
||||||
|
updated_at: this.metadata["date"],
|
||||||
|
published_at: this.metadata["date"],
|
||||||
|
tags: this.metadata["tags"],
|
||||||
|
author: process.env.AUTHOR_EMAIL,
|
||||||
|
feature_image: this.featureImage,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(JSON.stringify(this.metadata));
|
||||||
|
console.log(JSON.stringify(result));
|
||||||
|
|
||||||
|
if (process.env.PUSH_POSTS === "true") {
|
||||||
|
await api.posts.add(JSON.parse(result));
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
"Env PUSH_POST is configured so no posts are saved to the ghost instance."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies images and tries to process them
|
||||||
|
* @param api the ghost api reference
|
||||||
|
* @param basepath the path where to save images hosted online
|
||||||
|
*/
|
||||||
|
public async processImages(api: any, basepath: string) {
|
||||||
|
// collect images in an array
|
||||||
|
//let images: Record<string, StackedImage> = {};
|
||||||
|
const imageRegex = /!\[[^\]]*\]\((.*?)\s*("(?:.*[^"])")?\s*\)/g;
|
||||||
|
//let images: string[] = [];
|
||||||
|
//let m: any;
|
||||||
|
[
|
||||||
|
...this.content.matchAll(imageRegex),
|
||||||
|
["", "@@@" + this.metadata.cover, ""],
|
||||||
|
].forEach(async (item) => {
|
||||||
|
console.log(JSON.stringify(item));
|
||||||
|
|
||||||
|
let url = item[1];
|
||||||
|
let imageURL = url;
|
||||||
|
let imagePath = url;
|
||||||
|
|
||||||
|
let localpath = url;
|
||||||
|
|
||||||
|
if (url.startsWith("@@@")) {
|
||||||
|
localpath = "" + process.env.HEAD_IMAGE_PATH + url.slice(3);
|
||||||
|
} else {
|
||||||
|
localpath = path.join(path.dirname(this.filename), url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download images locally if not already
|
||||||
|
if (url.toLowerCase().startsWith("http")) {
|
||||||
|
// Download the image locally
|
||||||
|
let localpath = path.join(basepath, path.basename(url));
|
||||||
|
await downloadImagefromURL(url, localpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload the image to ghost
|
||||||
|
if (api) {
|
||||||
|
let reference = await uploadToGhost(api, localpath);
|
||||||
|
imageURL = reference.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace the image string with the new URL
|
||||||
|
console.log("replace", imagePath, " with ", imageURL);
|
||||||
|
this.content = this.content.replaceAll(imagePath, imageURL);
|
||||||
|
|
||||||
|
// Set the feature image if any
|
||||||
|
if (imagePath.startsWith("@@@")) {
|
||||||
|
this.setFeatureImage(imageURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug: show the updated content if necessary
|
||||||
|
// console.log(this.content);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
10
src/convertor/Convertor.ts
Normal file
10
src/convertor/Convertor.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export interface Convertor {
|
||||||
|
// The markdown bits (preamble and content)
|
||||||
|
//
|
||||||
|
filename: string;
|
||||||
|
content: string;
|
||||||
|
metadata: Record<string, any>;
|
||||||
|
|
||||||
|
process(api: any): void;
|
||||||
|
setFeatureImage(url: string): void;
|
||||||
|
}
|
@ -3,36 +3,43 @@ import fs from "fs";
|
|||||||
import MarkdownIt from "markdown-it";
|
import MarkdownIt from "markdown-it";
|
||||||
import Token from "markdown-it/lib/token";
|
import Token from "markdown-it/lib/token";
|
||||||
import metadataParser from "markdown-yaml-metadata-parser";
|
import metadataParser from "markdown-yaml-metadata-parser";
|
||||||
import { downloadImagefromURL, uploadToGhost } from "./images";
|
import { Convertor } from "./Convertor";
|
||||||
import path from "node:path";
|
|
||||||
|
const debugFence = false;
|
||||||
|
const debugInline = true;
|
||||||
|
const debugBlock = false;
|
||||||
|
const debugHeader = false;
|
||||||
|
|
||||||
interface Stack {
|
interface Stack {
|
||||||
tag: string;
|
tag: string;
|
||||||
meta: any;
|
meta: any;
|
||||||
token: Token;
|
token: Token;
|
||||||
}
|
}
|
||||||
interface StackedImage {
|
|
||||||
path: string;
|
|
||||||
url: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderer: any = Renderer;
|
const renderer: any = Renderer;
|
||||||
|
|
||||||
const predefinedBlocks = ["blockquote", "table", "bullet_list", "ordered_list"];
|
const predefinedBlocks = [
|
||||||
|
"blockquote",
|
||||||
|
"table",
|
||||||
|
"bullet_list",
|
||||||
|
"ordered_list",
|
||||||
|
"paragraph",
|
||||||
|
];
|
||||||
|
|
||||||
const headerAsMarkdown = true;
|
const headerAsMarkdown = true;
|
||||||
|
|
||||||
export class Convertor {
|
export class DetailedConvertor implements Convertor {
|
||||||
markups: Record<string, any> = {};
|
markups: Record<string, any> = {};
|
||||||
markers: Record<string, any> = {};
|
markers: Record<string, any> = {};
|
||||||
images: Record<string, StackedImage> = {};
|
|
||||||
sections: any[] = [];
|
sections: any[] = [];
|
||||||
builder: any = new PostNodeBuilder();
|
builder: any = new PostNodeBuilder();
|
||||||
|
filename: string;
|
||||||
|
|
||||||
// The markdown bits (preamble and content)
|
// The markdown bits (preamble and content)
|
||||||
//
|
//
|
||||||
preamble: string = "";
|
metadata = {};
|
||||||
content: string = "";
|
content = "";
|
||||||
|
|
||||||
// The line-by-line split of the markdown
|
// The line-by-line split of the markdown
|
||||||
//
|
//
|
||||||
@ -45,22 +52,26 @@ export class Convertor {
|
|||||||
* @param filename the file name
|
* @param filename the file name
|
||||||
*/
|
*/
|
||||||
constructor(filename: string) {
|
constructor(filename: string) {
|
||||||
|
this.filename = filename;
|
||||||
this.initialize(filename);
|
this.initialize(filename);
|
||||||
}
|
}
|
||||||
|
setFeatureImage(url: string): void {
|
||||||
|
throw new Error("Method not implemented.", url);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize/reset the convertor class.
|
* Initialize/reset the convertor class.
|
||||||
*
|
*
|
||||||
* @param filename The file to be loaded
|
* @param filename The file to be loaded
|
||||||
*/
|
*/
|
||||||
public initialize(filename: string): Convertor {
|
public initialize(filename: string): DetailedConvertor {
|
||||||
this.builder = new PostNodeBuilder();
|
this.builder = new PostNodeBuilder();
|
||||||
let content = fs.readFileSync(filename, {
|
let content = fs.readFileSync(filename, {
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
flag: "r",
|
flag: "r",
|
||||||
});
|
});
|
||||||
const parsed = metadataParser(content);
|
const parsed = metadataParser(content);
|
||||||
this.preamble = parsed.preamble;
|
this.metadata = parsed.metadata;
|
||||||
this.content = parsed.content;
|
this.content = parsed.content;
|
||||||
|
|
||||||
// Split the lines
|
// Split the lines
|
||||||
@ -73,7 +84,7 @@ export class Convertor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public process(): string {
|
public process(): string {
|
||||||
if (this.preamble === "" && this.content == "") {
|
if (this.metadata === undefined && this.content == "") {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Convertor not initialised. Please use initalize(...) first"
|
"Convertor not initialised. Please use initalize(...) first"
|
||||||
);
|
);
|
||||||
@ -87,6 +98,7 @@ export class Convertor {
|
|||||||
let components: string[] = value.type.split("_");
|
let components: string[] = value.type.split("_");
|
||||||
let action: string | undefined = components.pop();
|
let action: string | undefined = components.pop();
|
||||||
let name = components.join("_");
|
let name = components.join("_");
|
||||||
|
console.log("BEGIN: ", value.tag, value.type);
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case "open":
|
case "open":
|
||||||
if (name in predefinedBlocks) blockNesting++;
|
if (name in predefinedBlocks) blockNesting++;
|
||||||
@ -101,8 +113,9 @@ export class Convertor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
break;
|
break;
|
||||||
case "fence":
|
case "fence":
|
||||||
|
case "block":
|
||||||
if (blockNesting == 0) {
|
if (blockNesting == 0) {
|
||||||
console.log("Process fence...");
|
this.sections.push(this.processFence(value));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "inline":
|
case "inline":
|
||||||
@ -136,7 +149,8 @@ export class Convertor {
|
|||||||
this.processBlock(value);
|
this.processBlock(value);
|
||||||
}
|
}
|
||||||
} else if (blockNesting == 0 && action === "inline") {
|
} else if (blockNesting == 0 && action === "inline") {
|
||||||
console.log(value.level, stack[0].token.type);
|
if (debugInline)
|
||||||
|
console.log(value.level, stack[0].token.type, stack[0].tag);
|
||||||
switch (stack[0].token.type) {
|
switch (stack[0].token.type) {
|
||||||
case "heading_open":
|
case "heading_open":
|
||||||
this.sections.push(this.processHeader(stack, value));
|
this.sections.push(this.processHeader(stack, value));
|
||||||
@ -156,39 +170,87 @@ export class Convertor {
|
|||||||
author: "laur.ivan@gmail.com",
|
author: "laur.ivan@gmail.com",
|
||||||
});
|
});
|
||||||
console.log("BLOG ENTRY------------------------------------");
|
console.log("BLOG ENTRY------------------------------------");
|
||||||
console.log(result);
|
console.log(JSON.stringify(renderer.render(post, "0.3.1")));
|
||||||
console.log("BLOG ENTRY------------------------------------");
|
console.log("BLOG ENTRY------------------------------------");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private processInline(stack: Stack[], t: Token) {
|
private processInline(stack: Stack[], t: Token) {
|
||||||
console.log("*********************************************");
|
if (debugInline) {
|
||||||
console.log(stack.length, JSON.stringify(stack[0]));
|
console.log("processInline:", stack.length, JSON.stringify(stack[0]));
|
||||||
|
}
|
||||||
// build the header as a markdown card
|
// build the header as a markdown card
|
||||||
let tbuf: string[] = [];
|
let tbuf: string[] = [];
|
||||||
|
|
||||||
if (t.map != null)
|
if (t.map != null)
|
||||||
for (let i = t.map[0]; i < t.map[1]; i++) tbuf.push(this.lines[i]);
|
for (let i = t.map[0]; i < t.map[1]; i++) tbuf.push(this.lines[i]);
|
||||||
|
let markdown = this.map2markdown(t.map);
|
||||||
|
|
||||||
|
if (debugInline) {
|
||||||
|
console.log("processInline:", JSON.stringify(markdown));
|
||||||
|
}
|
||||||
|
|
||||||
let result = this.builder.createCardSection("markdown", {
|
let result = this.builder.createCardSection("markdown", {
|
||||||
markdown: tbuf.join("\n"),
|
markdown: markdown,
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private processBlock(t: Token) {
|
/**
|
||||||
|
* Get the string off lines range
|
||||||
|
*
|
||||||
|
* @param map the [lineStart, lineEnd] array
|
||||||
|
* @returns a sting containing the lines
|
||||||
|
*/
|
||||||
|
private map2markdown(map: [number, number] | null): string {
|
||||||
let tbuf: string[] = [];
|
let tbuf: string[] = [];
|
||||||
if (t.map != null)
|
if (map != null)
|
||||||
for (let i = t.map[0]; i < t.map[1]; i++) tbuf.push(this.lines[i]);
|
for (let i = map[0]; i < map[1]; i++) tbuf.push(this.lines[i]);
|
||||||
//console.log("----------------------------------------------------");
|
return tbuf.join("\n");
|
||||||
//console.log(JSON.stringify(t));
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a fence (or code block)
|
||||||
|
*
|
||||||
|
* @param t the token of the fence
|
||||||
|
* @returns a markdown card
|
||||||
|
*/
|
||||||
|
private processFence(t: Token): any {
|
||||||
|
let result;
|
||||||
|
|
||||||
|
if (debugFence) {
|
||||||
|
console.log("processFence:", console.log(JSON.stringify(t)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the fence as a markdown card
|
||||||
|
let markdown = this.map2markdown(t.map);
|
||||||
|
|
||||||
|
if (debugFence) {
|
||||||
|
console.log("processFence:", console.log(JSON.stringify(markdown)));
|
||||||
|
}
|
||||||
|
|
||||||
|
result = this.builder.createCardSection("markdown", {
|
||||||
|
markdown: markdown,
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private processBlock(t: Token): any {
|
||||||
|
let markdown = this.map2markdown(t.map);
|
||||||
|
if (debugBlock) {
|
||||||
|
console.log("processBlock", JSON.stringify(t));
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
content: tbuf.join("\n"),
|
content: markdown,
|
||||||
token: t,
|
token: t,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private processHeader(stack: Stack[], t: Token): any {
|
private processHeader(stack: Stack[], t: Token): any {
|
||||||
console.log("+++++++++++++++++++++++++++++++++++++++++++++");
|
if (debugHeader) {
|
||||||
console.log(JSON.stringify(stack[0].token));
|
console.log("processHeader", JSON.stringify(stack[0].token));
|
||||||
|
}
|
||||||
|
|
||||||
let result: any = undefined;
|
let result: any = undefined;
|
||||||
|
|
||||||
@ -198,66 +260,13 @@ export class Convertor {
|
|||||||
result = this.builder.createMarkupSection(stack[0].tag, [marker]);
|
result = this.builder.createMarkupSection(stack[0].tag, [marker]);
|
||||||
} else {
|
} else {
|
||||||
// build the header as a markdown card
|
// build the header as a markdown card
|
||||||
let tbuf: string[] = [];
|
let markdown = this.map2markdown(t.map);
|
||||||
if (t.map != null)
|
|
||||||
for (let i = t.map[0]; i < t.map[1]; i++) tbuf.push(this.lines[i]);
|
|
||||||
result = this.builder.createCardSection("markdown", {
|
result = this.builder.createCardSection("markdown", {
|
||||||
markdown: tbuf.join("\n"),
|
markdown: markdown,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Identifies images and tries to process them
|
|
||||||
*
|
|
||||||
* @returns this
|
|
||||||
*/
|
|
||||||
public async processImages(api: any, basepath: string) {
|
|
||||||
// collect images in an array
|
|
||||||
const imageRegex = /!\[[^\]]*\]\((.*?)\s*("(?:.*[^"])")?\s*\)/g;
|
|
||||||
//let images: string[] = [];
|
|
||||||
//let m: any;
|
|
||||||
[...this.content.matchAll(imageRegex)].forEach(async (item) => {
|
|
||||||
console.log(JSON.stringify(item));
|
|
||||||
if (item[1] in this.images) {
|
|
||||||
console.log("Skip cached image for URL: ", item[1]);
|
|
||||||
} else {
|
|
||||||
let url = item[1];
|
|
||||||
// Add the image to the cache of processed images
|
|
||||||
this.images[url] = {
|
|
||||||
path: url,
|
|
||||||
url: url,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Download images locally if not already
|
|
||||||
if (url.toLowerCase().startsWith("http")) {
|
|
||||||
// Download the image locally
|
|
||||||
let localpath = path.join(basepath, path.basename(url));
|
|
||||||
await downloadImagefromURL(url, localpath);
|
|
||||||
|
|
||||||
// Upload the image to ghost
|
|
||||||
if (api) {
|
|
||||||
let reference = await uploadToGhost(api, localpath);
|
|
||||||
this.images[url].url = reference.url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace the image string with the new URL
|
|
||||||
console.log(
|
|
||||||
"replace",
|
|
||||||
this.images[url].path,
|
|
||||||
" with ",
|
|
||||||
this.images[url].url
|
|
||||||
);
|
|
||||||
this.content = this.content.replaceAll(
|
|
||||||
this.images[url].path,
|
|
||||||
this.images[url].url
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(this.content);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
85
src/convertor/ImageProcessor.ts
Normal file
85
src/convertor/ImageProcessor.ts
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import * as dotenv from "dotenv";
|
||||||
|
import path from "node:path";
|
||||||
|
import { downloadImagefromURL, uploadToGhost } from "./images";
|
||||||
|
import { Convertor } from "./Convertor";
|
||||||
|
|
||||||
|
// Init config
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
|
export interface StackedImage {
|
||||||
|
path: string;
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ImageProcessor {
|
||||||
|
images: Record<string, StackedImage> = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies images and tries to process them
|
||||||
|
* @param api the ghost api reference
|
||||||
|
* @param basepath the path where to save images hosted online
|
||||||
|
*/
|
||||||
|
public async processImages(processor: Convertor, api: any, basepath: string) {
|
||||||
|
// collect images in an array
|
||||||
|
const imageRegex = /!\[[^\]]*\]\((.*?)\s*("(?:.*[^"])")?\s*\)/g;
|
||||||
|
//let images: string[] = [];
|
||||||
|
//let m: any;
|
||||||
|
[
|
||||||
|
...processor.content.matchAll(imageRegex),
|
||||||
|
["", "@@@" + processor.metadata.cover, ""],
|
||||||
|
].forEach(async (item) => {
|
||||||
|
console.log(JSON.stringify(item));
|
||||||
|
if (item[1] in this.images) {
|
||||||
|
console.log("Skip cached image for URL: ", item[1]);
|
||||||
|
} else {
|
||||||
|
let url = item[1];
|
||||||
|
// Add the image to the cache of processed images
|
||||||
|
this.images[url] = {
|
||||||
|
path: url,
|
||||||
|
url: url,
|
||||||
|
};
|
||||||
|
|
||||||
|
let localpath = url;
|
||||||
|
|
||||||
|
if (url.startsWith("@@@")) {
|
||||||
|
localpath = "" + process.env.HEAD_IMAGE_PATH + url.slice(3);
|
||||||
|
} else {
|
||||||
|
localpath = path.join(path.dirname(processor.filename), url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download images locally if not already
|
||||||
|
if (url.toLowerCase().startsWith("http")) {
|
||||||
|
// Download the image locally
|
||||||
|
let localpath = path.join(basepath, path.basename(url));
|
||||||
|
await downloadImagefromURL(url, localpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload the image to ghost
|
||||||
|
if (api) {
|
||||||
|
let reference = await uploadToGhost(api, localpath);
|
||||||
|
this.images[url].url = reference.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace the image string with the new URL
|
||||||
|
console.log(
|
||||||
|
"replace",
|
||||||
|
this.images[url].path,
|
||||||
|
" with ",
|
||||||
|
this.images[url].url
|
||||||
|
);
|
||||||
|
processor.content = processor.content.replaceAll(
|
||||||
|
this.images[url].path,
|
||||||
|
this.images[url].url
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set the feature image if any
|
||||||
|
if (this.images[url].path.startsWith("@@@")) {
|
||||||
|
processor.setFeatureImage(this.images[url].url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug: show the updated content if necessary
|
||||||
|
// console.log(this.content);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -45,16 +45,21 @@ export interface GhostReference {
|
|||||||
ref: string;
|
ref: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param api the Ghost API object
|
||||||
|
* @param filename the file name of the image to be uploaded
|
||||||
|
* @returns a GhostReference promise with the real file name.
|
||||||
|
*/
|
||||||
export async function uploadToGhost(
|
export async function uploadToGhost(
|
||||||
api: any,
|
api: any,
|
||||||
filename: string
|
filename: string
|
||||||
): Promise<GhostReference> {
|
): Promise<GhostReference> {
|
||||||
//const data: Buffer = fs.readFileSync(filename);
|
|
||||||
let image: Image = {
|
let image: Image = {
|
||||||
ref: path.basename(filename),
|
ref: path.basename(filename),
|
||||||
file: filename,
|
file: filename,
|
||||||
purpose: "image",
|
purpose: "image",
|
||||||
};
|
};
|
||||||
let result = api.images.upload(image);
|
let result = await api.images.upload(image);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
---
|
|
||||||
title: Basic markdown file
|
|
||||||
author: Laur IVAN
|
|
||||||
version: 1.0
|
|
||||||
date: "2022-06-24"
|
|
||||||
license: "[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)"
|
|
||||||
---
|
|
||||||
|
|
||||||
# H1 header
|
|
||||||
|
|
||||||
## H2 header
|
|
||||||
|
|
||||||
### H3 header
|
|
||||||
|
|
||||||
This is a paragraph
|
|
||||||
|
|
||||||
This is another paragraph.
|
|
||||||
With multipine.
|
|
||||||
|
|
||||||
- Bullet
|
|
||||||
- Bullet
|
|
||||||
- Bullet
|
|
||||||
|
|
||||||
1. Ordered list
|
|
||||||
1. Ordered list
|
|
||||||
1. Ordered list
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"code": "if(true) then true else false"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
| Table | Table |
|
|
||||||
+---+---+
|
|
||||||
| one | two |
|
|
||||||
| three | four |
|
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "A post",
|
|
||||||
"mobiledoc": "{\"version\":\"0.3.1\",\"atoms\":[],\"cards\":[[\"markdown\",{\"markdown\":\"```js\\nlet value = 0\\n```\"}]],\"markups\":[[\"strong\"]],\"sections\":[[1,\"p\",[[0,[0],0,\"Hi \"],[0,[],1,\" Bye\"]]],[10,0]]}",
|
|
||||||
"status": "draft",
|
|
||||||
"authors": ["laur.ivan@gmail.com"]
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "A post",
|
|
||||||
"slug": "a-post",
|
|
||||||
"mobiledoc": "{\"version\":\"0.3.1\",\"atoms\":[],\"cards\":[],\"markups\":[],\"sections\":[[1,\"p\",[[0,[],0,\"👋 Welcome, it's great to have you here.\"]]]]}",
|
|
||||||
"status": "published"
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "A post"
|
|
||||||
}
|
|
@ -1,450 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": "62b72926609faa00017b7f44",
|
|
||||||
"uuid": "948abc50-4233-4c29-8429-3fa75eba6610",
|
|
||||||
"title": "This is the title",
|
|
||||||
"slug": "this-is-the-title",
|
|
||||||
"mobiledoc": "{\"version\":\"0.3.1\",\"atoms\":[],\"cards\":[],\"markups\":[[\"strong\"],[\"em\"]],\"sections\":[[1,\"p\",[[0,[],0,\"I am \"],[0,[0],1,\"writing \"],[0,[],0,\"my \"],[0,[1],1,\"post @laur\"]]]],\"ghostVersion\":\"4.0\"}",
|
|
||||||
"comment_id": "62b72926609faa00017b7f44",
|
|
||||||
"feature_image": null,
|
|
||||||
"featured": false,
|
|
||||||
"status": "published",
|
|
||||||
"visibility": "public",
|
|
||||||
"created_at": "2022-06-25T15:26:30.000Z",
|
|
||||||
"updated_at": "2022-06-25T15:27:08.000Z",
|
|
||||||
"published_at": "2022-06-25T15:27:08.000Z",
|
|
||||||
"custom_excerpt": null,
|
|
||||||
"codeinjection_head": null,
|
|
||||||
"codeinjection_foot": null,
|
|
||||||
"custom_template": null,
|
|
||||||
"canonical_url": null,
|
|
||||||
"tags": [],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-25T15:27:07.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-25T15:27:07.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tiers": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29c",
|
|
||||||
"name": "Free",
|
|
||||||
"slug": "free",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "free",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29d",
|
|
||||||
"name": "Laur's blog",
|
|
||||||
"slug": "default-product",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "paid",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:29:05.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primary_author": {
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-25T15:27:07.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-25T15:27:07.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
},
|
|
||||||
"primary_tag": null,
|
|
||||||
"email_segment": "all",
|
|
||||||
"url": "http://localhost:2368/this-is-the-title/",
|
|
||||||
"excerpt": "I am writing my post @laur",
|
|
||||||
"og_image": null,
|
|
||||||
"og_title": null,
|
|
||||||
"og_description": null,
|
|
||||||
"twitter_image": null,
|
|
||||||
"twitter_title": null,
|
|
||||||
"twitter_description": null,
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"email_subject": null,
|
|
||||||
"frontmatter": null,
|
|
||||||
"feature_image_alt": null,
|
|
||||||
"feature_image_caption": null,
|
|
||||||
"email_only": false,
|
|
||||||
"email": null,
|
|
||||||
"newsletter": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "62960a928b281d00012eb478",
|
|
||||||
"uuid": "e50c8ca6-055d-483e-ba27-bbb3bc2f854a",
|
|
||||||
"title": "I really want this",
|
|
||||||
"slug": "i-really-want-this",
|
|
||||||
"mobiledoc": "{\"version\":\"0.3.1\",\"atoms\":[],\"cards\":[[\"markdown\",{\"markdown\":\"## I am very markdowny\"}],[\"markdown\",{\"markdown\":\"```json\\n{\\n \\\"a\\\": true\\n}\\n```\\n\\n| one | two | three | four | five |\\n|---|---|---|---|---|\\n| row | | | | |\\n| row | | | | |\\n| row | | | | row |\"}]],\"markups\":[],\"sections\":[[1,\"p\",[[0,[],0,\"Some markdown to be put here\"]]],[10,0],[10,1],[1,\"p\",[]]],\"ghostVersion\":\"4.0\"}",
|
|
||||||
"comment_id": "62960a928b281d00012eb478",
|
|
||||||
"feature_image": null,
|
|
||||||
"featured": false,
|
|
||||||
"status": "published",
|
|
||||||
"visibility": "public",
|
|
||||||
"created_at": "2022-05-31T12:31:14.000Z",
|
|
||||||
"updated_at": "2022-06-15T18:15:52.000Z",
|
|
||||||
"published_at": "2022-06-15T18:13:26.000Z",
|
|
||||||
"custom_excerpt": null,
|
|
||||||
"codeinjection_head": null,
|
|
||||||
"codeinjection_foot": null,
|
|
||||||
"custom_template": null,
|
|
||||||
"canonical_url": null,
|
|
||||||
"tags": [],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-25T15:27:07.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-25T15:27:07.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tiers": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29c",
|
|
||||||
"name": "Free",
|
|
||||||
"slug": "free",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "free",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29d",
|
|
||||||
"name": "Laur's blog",
|
|
||||||
"slug": "default-product",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "paid",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:29:05.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primary_author": {
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-25T15:27:07.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-25T15:27:07.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
},
|
|
||||||
"primary_tag": null,
|
|
||||||
"email_segment": "all",
|
|
||||||
"url": "http://localhost:2368/i-really-want-this/",
|
|
||||||
"excerpt": "Some markdown to be put here\n\n\nI am very markdowny\n\n\n{\n \"a\": true\n}\n\n\n\n\n\n\none\ntwo\nthree\nfour\nfive\n\n\n\n\nrow\n\n\n\n\n\n\nrow\n\n\n\n\n\n\nrow\n\n\n\nrow\n\n\n\n",
|
|
||||||
"og_image": null,
|
|
||||||
"og_title": null,
|
|
||||||
"og_description": null,
|
|
||||||
"twitter_image": null,
|
|
||||||
"twitter_title": null,
|
|
||||||
"twitter_description": null,
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"email_subject": null,
|
|
||||||
"frontmatter": null,
|
|
||||||
"feature_image_alt": null,
|
|
||||||
"feature_image_caption": null,
|
|
||||||
"email_only": false,
|
|
||||||
"email": null,
|
|
||||||
"newsletter": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb300",
|
|
||||||
"uuid": "49d5c2d3-2aa8-4ea9-9682-47da5c4b73fd",
|
|
||||||
"title": "Coming really soon",
|
|
||||||
"slug": "coming-soon",
|
|
||||||
"mobiledoc": "{\"version\":\"0.3.1\",\"atoms\":[],\"cards\":[],\"markups\":[[\"a\",[\"href\",\"#/portal/\"]]],\"sections\":[[1,\"p\",[[0,[],0,\"This is Laur's blog, a brand new site by Laur Ivan that's just getting started. Things will be up and running here shortly, but you can \"],[0,[0],1,\"subscribe\"],[0,[],0,\" in the meantime if you'd like to stay up to date and receive emails when new content is published!\"]]]],\"ghostVersion\":\"4.0\"}",
|
|
||||||
"comment_id": "629609ae8b281d00012eb300",
|
|
||||||
"feature_image": "https://static.ghost.org/v4.0.0/images/feature-image.jpg",
|
|
||||||
"featured": false,
|
|
||||||
"status": "published",
|
|
||||||
"visibility": "public",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:30:09.000Z",
|
|
||||||
"published_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"custom_excerpt": null,
|
|
||||||
"codeinjection_head": null,
|
|
||||||
"codeinjection_foot": null,
|
|
||||||
"custom_template": null,
|
|
||||||
"canonical_url": null,
|
|
||||||
"tags": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29f",
|
|
||||||
"name": "News",
|
|
||||||
"slug": "news",
|
|
||||||
"description": null,
|
|
||||||
"feature_image": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"og_image": null,
|
|
||||||
"og_title": null,
|
|
||||||
"og_description": null,
|
|
||||||
"twitter_image": null,
|
|
||||||
"twitter_title": null,
|
|
||||||
"twitter_description": null,
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"codeinjection_head": null,
|
|
||||||
"codeinjection_foot": null,
|
|
||||||
"canonical_url": null,
|
|
||||||
"accent_color": null,
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:30:09.000Z",
|
|
||||||
"url": "http://localhost:2368/tag/news/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-25T15:27:07.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-25T15:27:07.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tiers": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29c",
|
|
||||||
"name": "Free",
|
|
||||||
"slug": "free",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "free",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29d",
|
|
||||||
"name": "Laur's blog",
|
|
||||||
"slug": "default-product",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "paid",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:29:05.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primary_author": {
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-25T15:27:07.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-25T15:27:07.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
},
|
|
||||||
"primary_tag": {
|
|
||||||
"id": "629609ae8b281d00012eb29f",
|
|
||||||
"name": "News",
|
|
||||||
"slug": "news",
|
|
||||||
"description": null,
|
|
||||||
"feature_image": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"og_image": null,
|
|
||||||
"og_title": null,
|
|
||||||
"og_description": null,
|
|
||||||
"twitter_image": null,
|
|
||||||
"twitter_title": null,
|
|
||||||
"twitter_description": null,
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"codeinjection_head": null,
|
|
||||||
"codeinjection_foot": null,
|
|
||||||
"canonical_url": null,
|
|
||||||
"accent_color": null,
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:30:09.000Z",
|
|
||||||
"url": "http://localhost:2368/tag/news/"
|
|
||||||
},
|
|
||||||
"email_segment": "all",
|
|
||||||
"url": "http://localhost:2368/coming-soon/",
|
|
||||||
"excerpt": "This is Laur's blog, a brand new site by Laur Ivan that's just getting started. Things will be up and running here shortly, but you can subscribe in the meantime if you'd like to stay up to date and receive emails when new content is published!",
|
|
||||||
"og_image": null,
|
|
||||||
"og_title": null,
|
|
||||||
"og_description": null,
|
|
||||||
"twitter_image": null,
|
|
||||||
"twitter_title": null,
|
|
||||||
"twitter_description": null,
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"email_subject": null,
|
|
||||||
"frontmatter": null,
|
|
||||||
"feature_image_alt": null,
|
|
||||||
"feature_image_caption": null,
|
|
||||||
"email_only": false,
|
|
||||||
"email": null,
|
|
||||||
"newsletter": null
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,182 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": "62b81b265fb4ca000119c894",
|
|
||||||
"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,\"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-28T13:31:24.000Z",
|
|
||||||
"published_at": "2022-06-26T08:39:23.000Z",
|
|
||||||
"custom_excerpt": null,
|
|
||||||
"codeinjection_head": null,
|
|
||||||
"codeinjection_foot": null,
|
|
||||||
"custom_template": null,
|
|
||||||
"canonical_url": null,
|
|
||||||
"tags": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29f",
|
|
||||||
"name": "News",
|
|
||||||
"slug": "news",
|
|
||||||
"description": null,
|
|
||||||
"feature_image": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"og_image": null,
|
|
||||||
"og_title": null,
|
|
||||||
"og_description": null,
|
|
||||||
"twitter_image": null,
|
|
||||||
"twitter_title": null,
|
|
||||||
"twitter_description": null,
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"codeinjection_head": null,
|
|
||||||
"codeinjection_foot": null,
|
|
||||||
"canonical_url": null,
|
|
||||||
"accent_color": null,
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-28T13:31:24.000Z",
|
|
||||||
"url": "http://localhost:2368/tag/news/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-28T13:30:38.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-28T13:30:38.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tiers": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29c",
|
|
||||||
"name": "Free",
|
|
||||||
"slug": "free",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "free",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29d",
|
|
||||||
"name": "Laur's blog",
|
|
||||||
"slug": "default-product",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "paid",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:29:05.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primary_author": {
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-28T13:30:38.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-28T13:30:38.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
},
|
|
||||||
"primary_tag": {
|
|
||||||
"id": "629609ae8b281d00012eb29f",
|
|
||||||
"name": "News",
|
|
||||||
"slug": "news",
|
|
||||||
"description": null,
|
|
||||||
"feature_image": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"og_image": null,
|
|
||||||
"og_title": null,
|
|
||||||
"og_description": null,
|
|
||||||
"twitter_image": null,
|
|
||||||
"twitter_title": null,
|
|
||||||
"twitter_description": null,
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"codeinjection_head": null,
|
|
||||||
"codeinjection_foot": null,
|
|
||||||
"canonical_url": null,
|
|
||||||
"accent_color": null,
|
|
||||||
"created_at": "2022-05-31T12:27:26.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\n\n\nA title\n\n\nA second title",
|
|
||||||
"og_image": null,
|
|
||||||
"og_title": null,
|
|
||||||
"og_description": null,
|
|
||||||
"twitter_image": null,
|
|
||||||
"twitter_title": null,
|
|
||||||
"twitter_description": null,
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"email_subject": null,
|
|
||||||
"frontmatter": null,
|
|
||||||
"feature_image_alt": null,
|
|
||||||
"feature_image_caption": null,
|
|
||||||
"email_only": false,
|
|
||||||
"email": null,
|
|
||||||
"newsletter": null
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,450 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": "62af12d78bab0400019822ae",
|
|
||||||
"uuid": "98737bca-331d-4812-9b19-e6737ece9aa7",
|
|
||||||
"title": "Hello world",
|
|
||||||
"slug": "hello-world",
|
|
||||||
"mobiledoc": "{\"version\":\"0.3.1\",\"ghostVersion\":\"4.0\",\"markups\":[],\"atoms\":[],\"cards\":[],\"sections\":[[1,\"p\",[[0,[],0,\"\"]]]]}",
|
|
||||||
"comment_id": "62af12d78bab0400019822ae",
|
|
||||||
"feature_image": null,
|
|
||||||
"featured": false,
|
|
||||||
"status": "draft",
|
|
||||||
"visibility": "public",
|
|
||||||
"created_at": "2022-06-19T12:13:11.000Z",
|
|
||||||
"updated_at": "2022-06-19T12:13:11.000Z",
|
|
||||||
"published_at": null,
|
|
||||||
"custom_excerpt": null,
|
|
||||||
"codeinjection_head": null,
|
|
||||||
"codeinjection_foot": null,
|
|
||||||
"custom_template": null,
|
|
||||||
"canonical_url": null,
|
|
||||||
"tags": [],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-19T12:07:51.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-19T12:07:51.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tiers": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29c",
|
|
||||||
"name": "Free",
|
|
||||||
"slug": "free",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "free",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29d",
|
|
||||||
"name": "Laur's blog",
|
|
||||||
"slug": "default-product",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "paid",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:29:05.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primary_author": {
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-19T12:07:51.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-19T12:07:51.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
},
|
|
||||||
"primary_tag": null,
|
|
||||||
"email_segment": "all",
|
|
||||||
"url": "http://localhost:2368/p/98737bca-331d-4812-9b19-e6737ece9aa7/",
|
|
||||||
"excerpt": null,
|
|
||||||
"og_image": null,
|
|
||||||
"og_title": null,
|
|
||||||
"og_description": null,
|
|
||||||
"twitter_image": null,
|
|
||||||
"twitter_title": null,
|
|
||||||
"twitter_description": null,
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"email_subject": null,
|
|
||||||
"frontmatter": null,
|
|
||||||
"feature_image_alt": null,
|
|
||||||
"feature_image_caption": null,
|
|
||||||
"email_only": false,
|
|
||||||
"email": null,
|
|
||||||
"newsletter": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "62960a928b281d00012eb478",
|
|
||||||
"uuid": "e50c8ca6-055d-483e-ba27-bbb3bc2f854a",
|
|
||||||
"title": "I really want this",
|
|
||||||
"slug": "i-really-want-this",
|
|
||||||
"mobiledoc": "{\"version\":\"0.3.1\",\"atoms\":[],\"cards\":[[\"markdown\",{\"markdown\":\"## I am very markdowny\"}],[\"markdown\",{\"markdown\":\"```json\\n{\\n \\\"a\\\": true\\n}\\n```\\n\\n| one | two | three | four | five |\\n|---|---|---|---|---|\\n| row | | | | |\\n| row | | | | |\\n| row | | | | row |\"}]],\"markups\":[],\"sections\":[[1,\"p\",[[0,[],0,\"Some markdown to be put here\"]]],[10,0],[10,1],[1,\"p\",[]]],\"ghostVersion\":\"4.0\"}",
|
|
||||||
"comment_id": "62960a928b281d00012eb478",
|
|
||||||
"feature_image": null,
|
|
||||||
"featured": false,
|
|
||||||
"status": "published",
|
|
||||||
"visibility": "public",
|
|
||||||
"created_at": "2022-05-31T12:31:14.000Z",
|
|
||||||
"updated_at": "2022-06-15T18:15:52.000Z",
|
|
||||||
"published_at": "2022-06-15T18:13:26.000Z",
|
|
||||||
"custom_excerpt": null,
|
|
||||||
"codeinjection_head": null,
|
|
||||||
"codeinjection_foot": null,
|
|
||||||
"custom_template": null,
|
|
||||||
"canonical_url": null,
|
|
||||||
"tags": [],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-19T12:07:51.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-19T12:07:51.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tiers": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29c",
|
|
||||||
"name": "Free",
|
|
||||||
"slug": "free",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "free",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29d",
|
|
||||||
"name": "Laur's blog",
|
|
||||||
"slug": "default-product",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "paid",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:29:05.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primary_author": {
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-19T12:07:51.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-19T12:07:51.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
},
|
|
||||||
"primary_tag": null,
|
|
||||||
"email_segment": "all",
|
|
||||||
"url": "http://localhost:2368/i-really-want-this/",
|
|
||||||
"excerpt": "Some markdown to be put here\n\n\nI am very markdowny\n\n\n{\n \"a\": true\n}\n\n\n\n\n\n\none\ntwo\nthree\nfour\nfive\n\n\n\n\nrow\n\n\n\n\n\n\nrow\n\n\n\n\n\n\nrow\n\n\n\nrow\n\n\n\n",
|
|
||||||
"og_image": null,
|
|
||||||
"og_title": null,
|
|
||||||
"og_description": null,
|
|
||||||
"twitter_image": null,
|
|
||||||
"twitter_title": null,
|
|
||||||
"twitter_description": null,
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"email_subject": null,
|
|
||||||
"frontmatter": null,
|
|
||||||
"feature_image_alt": null,
|
|
||||||
"feature_image_caption": null,
|
|
||||||
"email_only": false,
|
|
||||||
"email": null,
|
|
||||||
"newsletter": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb300",
|
|
||||||
"uuid": "49d5c2d3-2aa8-4ea9-9682-47da5c4b73fd",
|
|
||||||
"title": "Coming really soon",
|
|
||||||
"slug": "coming-soon",
|
|
||||||
"mobiledoc": "{\"version\":\"0.3.1\",\"atoms\":[],\"cards\":[],\"markups\":[[\"a\",[\"href\",\"#/portal/\"]]],\"sections\":[[1,\"p\",[[0,[],0,\"This is Laur's blog, a brand new site by Laur Ivan that's just getting started. Things will be up and running here shortly, but you can \"],[0,[0],1,\"subscribe\"],[0,[],0,\" in the meantime if you'd like to stay up to date and receive emails when new content is published!\"]]]],\"ghostVersion\":\"4.0\"}",
|
|
||||||
"comment_id": "629609ae8b281d00012eb300",
|
|
||||||
"feature_image": "https://static.ghost.org/v4.0.0/images/feature-image.jpg",
|
|
||||||
"featured": false,
|
|
||||||
"status": "published",
|
|
||||||
"visibility": "public",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:30:09.000Z",
|
|
||||||
"published_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"custom_excerpt": null,
|
|
||||||
"codeinjection_head": null,
|
|
||||||
"codeinjection_foot": null,
|
|
||||||
"custom_template": null,
|
|
||||||
"canonical_url": null,
|
|
||||||
"tags": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29f",
|
|
||||||
"name": "News",
|
|
||||||
"slug": "news",
|
|
||||||
"description": null,
|
|
||||||
"feature_image": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"og_image": null,
|
|
||||||
"og_title": null,
|
|
||||||
"og_description": null,
|
|
||||||
"twitter_image": null,
|
|
||||||
"twitter_title": null,
|
|
||||||
"twitter_description": null,
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"codeinjection_head": null,
|
|
||||||
"codeinjection_foot": null,
|
|
||||||
"canonical_url": null,
|
|
||||||
"accent_color": null,
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:30:09.000Z",
|
|
||||||
"url": "http://localhost:2368/tag/news/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-19T12:07:51.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-19T12:07:51.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tiers": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29c",
|
|
||||||
"name": "Free",
|
|
||||||
"slug": "free",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "free",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb29d",
|
|
||||||
"name": "Laur's blog",
|
|
||||||
"slug": "default-product",
|
|
||||||
"active": true,
|
|
||||||
"welcome_page_url": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"monthly_price_id": null,
|
|
||||||
"yearly_price_id": null,
|
|
||||||
"description": null,
|
|
||||||
"type": "paid",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:29:05.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primary_author": {
|
|
||||||
"id": "1",
|
|
||||||
"name": "Laur Ivan",
|
|
||||||
"slug": "laur",
|
|
||||||
"email": "laur.ivan@gmail.com",
|
|
||||||
"profile_image": "https://www.gravatar.com/avatar/1abe88862a65973704f7c9b028cf7afe?s=250&r=x&d=mp",
|
|
||||||
"cover_image": null,
|
|
||||||
"bio": null,
|
|
||||||
"website": null,
|
|
||||||
"location": null,
|
|
||||||
"facebook": null,
|
|
||||||
"twitter": null,
|
|
||||||
"accessibility": "{\"nightShift\":true}",
|
|
||||||
"status": "active",
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"tour": null,
|
|
||||||
"last_seen": "2022-06-19T12:07:51.000Z",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-06-19T12:07:51.000Z",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"id": "629609ae8b281d00012eb297",
|
|
||||||
"name": "Owner",
|
|
||||||
"description": "Blog Owner",
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:27:26.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": "http://localhost:2368/author/laur/"
|
|
||||||
},
|
|
||||||
"primary_tag": {
|
|
||||||
"id": "629609ae8b281d00012eb29f",
|
|
||||||
"name": "News",
|
|
||||||
"slug": "news",
|
|
||||||
"description": null,
|
|
||||||
"feature_image": null,
|
|
||||||
"visibility": "public",
|
|
||||||
"og_image": null,
|
|
||||||
"og_title": null,
|
|
||||||
"og_description": null,
|
|
||||||
"twitter_image": null,
|
|
||||||
"twitter_title": null,
|
|
||||||
"twitter_description": null,
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"codeinjection_head": null,
|
|
||||||
"codeinjection_foot": null,
|
|
||||||
"canonical_url": null,
|
|
||||||
"accent_color": null,
|
|
||||||
"created_at": "2022-05-31T12:27:26.000Z",
|
|
||||||
"updated_at": "2022-05-31T12:30:09.000Z",
|
|
||||||
"url": "http://localhost:2368/tag/news/"
|
|
||||||
},
|
|
||||||
"email_segment": "all",
|
|
||||||
"url": "http://localhost:2368/coming-soon/",
|
|
||||||
"excerpt": "This is Laur's blog, a brand new site by Laur Ivan that's just getting started. Things will be up and running here shortly, but you can subscribe in the meantime if you'd like to stay up to date and receive emails when new content is published!",
|
|
||||||
"og_image": null,
|
|
||||||
"og_title": null,
|
|
||||||
"og_description": null,
|
|
||||||
"twitter_image": null,
|
|
||||||
"twitter_title": null,
|
|
||||||
"twitter_description": null,
|
|
||||||
"meta_title": null,
|
|
||||||
"meta_description": null,
|
|
||||||
"email_subject": null,
|
|
||||||
"frontmatter": null,
|
|
||||||
"feature_image_alt": null,
|
|
||||||
"feature_image_caption": null,
|
|
||||||
"email_only": false,
|
|
||||||
"email": null,
|
|
||||||
"newsletter": null
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,240 +0,0 @@
|
|||||||
---
|
|
||||||
title: Basic markdown file (markdown.it example)
|
|
||||||
author: Laur IVAN
|
|
||||||
version: 1.0
|
|
||||||
date: "2022-06-24"
|
|
||||||
license: "[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)"
|
|
||||||
---
|
|
||||||
|
|
||||||
**Advertisement :)**
|
|
||||||
|
|
||||||
- **[pica](https://nodeca.github.io/pica/demo/)** - high quality and fast image
|
|
||||||
resize in browser.
|
|
||||||
- **[babelfish](https://github.com/nodeca/babelfish/)** - developer friendly
|
|
||||||
i18n with plurals support and easy syntax.
|
|
||||||
|
|
||||||
You will like those projects!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# h1 Heading 8-)
|
|
||||||
|
|
||||||
## h2 Heading
|
|
||||||
|
|
||||||
### h3 Heading
|
|
||||||
|
|
||||||
#### h4 Heading
|
|
||||||
|
|
||||||
##### h5 Heading
|
|
||||||
|
|
||||||
###### h6 Heading
|
|
||||||
|
|
||||||
## Horizontal Rules
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Typographic replacements
|
|
||||||
|
|
||||||
Enable typographer option to see result.
|
|
||||||
|
|
||||||
(c) (C) (r) (R) (tm) (TM) (p) (P) +-
|
|
||||||
|
|
||||||
test.. test... test..... test?..... test!....
|
|
||||||
|
|
||||||
!!!!!! ???? ,, -- ---
|
|
||||||
|
|
||||||
"Smartypants, double quotes" and 'single quotes'
|
|
||||||
|
|
||||||
## Emphasis
|
|
||||||
|
|
||||||
**This is bold text**
|
|
||||||
|
|
||||||
**This is bold text**
|
|
||||||
|
|
||||||
_This is italic text_
|
|
||||||
|
|
||||||
_This is italic text_
|
|
||||||
|
|
||||||
~~Strikethrough~~
|
|
||||||
|
|
||||||
## Blockquotes
|
|
||||||
|
|
||||||
> Blockquotes can also be nested...
|
|
||||||
>
|
|
||||||
> > ...by using additional greater-than signs right next to each other...
|
|
||||||
> >
|
|
||||||
> > > ...or with spaces between arrows.
|
|
||||||
|
|
||||||
## Lists
|
|
||||||
|
|
||||||
Unordered
|
|
||||||
|
|
||||||
- Create a list by starting a line with `+`, `-`, or `*`
|
|
||||||
- Sub-lists are made by indenting 2 spaces:
|
|
||||||
- Marker character change forces new list start:
|
|
||||||
- Ac tristique libero volutpat at
|
|
||||||
* Facilisis in pretium nisl aliquet
|
|
||||||
- Nulla volutpat aliquam velit
|
|
||||||
- Very easy!
|
|
||||||
|
|
||||||
Ordered
|
|
||||||
|
|
||||||
1. Lorem ipsum dolor sit amet
|
|
||||||
2. Consectetur adipiscing elit
|
|
||||||
3. Integer molestie lorem at massa
|
|
||||||
|
|
||||||
4. You can use sequential numbers...
|
|
||||||
5. ...or keep all the numbers as `1.`
|
|
||||||
|
|
||||||
Start numbering with offset:
|
|
||||||
|
|
||||||
57. foo
|
|
||||||
1. bar
|
|
||||||
|
|
||||||
## Code
|
|
||||||
|
|
||||||
Inline `code`
|
|
||||||
|
|
||||||
Indented code
|
|
||||||
|
|
||||||
// Some comments
|
|
||||||
line 1 of code
|
|
||||||
line 2 of code
|
|
||||||
line 3 of code
|
|
||||||
|
|
||||||
Block code "fences"
|
|
||||||
|
|
||||||
```
|
|
||||||
Sample text here...
|
|
||||||
```
|
|
||||||
|
|
||||||
Syntax highlighting
|
|
||||||
|
|
||||||
```js
|
|
||||||
var foo = function (bar) {
|
|
||||||
return bar++;
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log(foo(5));
|
|
||||||
```
|
|
||||||
|
|
||||||
## Tables
|
|
||||||
|
|
||||||
| Option | Description |
|
|
||||||
| ------ | ------------------------------------------------------------------------- |
|
|
||||||
| data | path to data files to supply the data that will be passed into templates. |
|
|
||||||
| engine | engine to be used for processing templates. Handlebars is the default. |
|
|
||||||
| ext | extension to be used for dest files. |
|
|
||||||
|
|
||||||
Right aligned columns
|
|
||||||
|
|
||||||
| Option | Description |
|
|
||||||
| -----: | ------------------------------------------------------------------------: |
|
|
||||||
| data | path to data files to supply the data that will be passed into templates. |
|
|
||||||
| engine | engine to be used for processing templates. Handlebars is the default. |
|
|
||||||
| ext | extension to be used for dest files. |
|
|
||||||
|
|
||||||
## Links
|
|
||||||
|
|
||||||
[link text](http://dev.nodeca.com)
|
|
||||||
|
|
||||||
[link with title](http://nodeca.github.io/pica/demo/ "title text!")
|
|
||||||
|
|
||||||
Autoconverted link https://github.com/nodeca/pica (enable linkify to see)
|
|
||||||
|
|
||||||
## Images
|
|
||||||
|
|
||||||
![Minion](https://octodex.github.com/images/minion.png)
|
|
||||||
![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat")
|
|
||||||
|
|
||||||
Like links, Images also have a footnote style syntax
|
|
||||||
|
|
||||||
![Alt text][id]
|
|
||||||
|
|
||||||
With a reference later in the document defining the URL location:
|
|
||||||
|
|
||||||
[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat"
|
|
||||||
|
|
||||||
## Plugins
|
|
||||||
|
|
||||||
The killer feature of `markdown-it` is very effective support of
|
|
||||||
[syntax plugins](https://www.npmjs.org/browse/keyword/markdown-it-plugin).
|
|
||||||
|
|
||||||
### [Emojies](https://github.com/markdown-it/markdown-it-emoji)
|
|
||||||
|
|
||||||
> Classic markup: :wink: :crush: :cry: :tear: :laughing: :yum:
|
|
||||||
>
|
|
||||||
> Shortcuts (emoticons): :-) :-( 8-) ;)
|
|
||||||
|
|
||||||
see [how to change output](https://github.com/markdown-it/markdown-it-emoji#change-output) with twemoji.
|
|
||||||
|
|
||||||
### [Subscript](https://github.com/markdown-it/markdown-it-sub) / [Superscript](https://github.com/markdown-it/markdown-it-sup)
|
|
||||||
|
|
||||||
- 19^th^
|
|
||||||
- H~2~O
|
|
||||||
|
|
||||||
### [\<ins>](https://github.com/markdown-it/markdown-it-ins)
|
|
||||||
|
|
||||||
++Inserted text++
|
|
||||||
|
|
||||||
### [\<mark>](https://github.com/markdown-it/markdown-it-mark)
|
|
||||||
|
|
||||||
==Marked text==
|
|
||||||
|
|
||||||
### [Footnotes](https://github.com/markdown-it/markdown-it-footnote)
|
|
||||||
|
|
||||||
Footnote 1 link[^first].
|
|
||||||
|
|
||||||
Footnote 2 link[^second].
|
|
||||||
|
|
||||||
Inline footnote^[Text of inline footnote] definition.
|
|
||||||
|
|
||||||
Duplicated footnote reference[^second].
|
|
||||||
|
|
||||||
[^first]: Footnote **can have markup**
|
|
||||||
|
|
||||||
and multiple paragraphs.
|
|
||||||
|
|
||||||
[^second]: Footnote text.
|
|
||||||
|
|
||||||
### [Definition lists](https://github.com/markdown-it/markdown-it-deflist)
|
|
||||||
|
|
||||||
Term 1
|
|
||||||
|
|
||||||
: Definition 1
|
|
||||||
with lazy continuation.
|
|
||||||
|
|
||||||
Term 2 with _inline markup_
|
|
||||||
|
|
||||||
: Definition 2
|
|
||||||
|
|
||||||
{ some code, part of Definition 2 }
|
|
||||||
|
|
||||||
Third paragraph of definition 2.
|
|
||||||
|
|
||||||
_Compact style:_
|
|
||||||
|
|
||||||
Term 1
|
|
||||||
~ Definition 1
|
|
||||||
|
|
||||||
Term 2
|
|
||||||
~ Definition 2a
|
|
||||||
~ Definition 2b
|
|
||||||
|
|
||||||
### [Abbreviations](https://github.com/markdown-it/markdown-it-abbr)
|
|
||||||
|
|
||||||
This is HTML abbreviation example.
|
|
||||||
|
|
||||||
It converts "HTML", but keep intact partial entries like "xxxHTMLyyy" and so on.
|
|
||||||
|
|
||||||
\*[HTML]: Hyper Text Markup Language
|
|
||||||
|
|
||||||
### [Custom containers](https://github.com/markdown-it/markdown-it-container)
|
|
||||||
|
|
||||||
::: warning
|
|
||||||
_here be dragons_
|
|
||||||
:::
|
|
9141
src/data/spec.md
9141
src/data/spec.md
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user