Basic ghost plugin
parent
6ebf8e7f15
commit
8fafd1cd4a
|
@ -9,7 +9,7 @@ export type MarkdownTree = {
|
|||
children?: MarkdownTree[];
|
||||
};
|
||||
|
||||
function treeToAST(text: string, n: SyntaxNode): MarkdownTree {
|
||||
function treeToAST(text: string, n: SyntaxNode, offset = 0): MarkdownTree {
|
||||
let children: MarkdownTree[] = [];
|
||||
let nodeText: string | undefined;
|
||||
let child = n.firstChild;
|
||||
|
@ -21,8 +21,8 @@ function treeToAST(text: string, n: SyntaxNode): MarkdownTree {
|
|||
if (children.length === 0) {
|
||||
children = [
|
||||
{
|
||||
from: n.from,
|
||||
to: n.to,
|
||||
from: n.from + offset,
|
||||
to: n.to + offset,
|
||||
text: text.substring(n.from, n.to),
|
||||
},
|
||||
];
|
||||
|
@ -33,8 +33,8 @@ function treeToAST(text: string, n: SyntaxNode): MarkdownTree {
|
|||
let s = text.substring(index, child.from);
|
||||
if (s) {
|
||||
newChildren.push({
|
||||
from: index,
|
||||
to: child.from,
|
||||
from: index + offset,
|
||||
to: child.from! + offset,
|
||||
text: s,
|
||||
});
|
||||
}
|
||||
|
@ -43,15 +43,15 @@ function treeToAST(text: string, n: SyntaxNode): MarkdownTree {
|
|||
}
|
||||
let s = text.substring(index, n.to);
|
||||
if (s) {
|
||||
newChildren.push({ from: index, to: n.to, text: s });
|
||||
newChildren.push({ from: index + offset, to: n.to + offset, text: s });
|
||||
}
|
||||
children = newChildren;
|
||||
}
|
||||
|
||||
let result: MarkdownTree = {
|
||||
type: n.name,
|
||||
from: n.from,
|
||||
to: n.to,
|
||||
from: n.from + offset,
|
||||
to: n.to + offset,
|
||||
};
|
||||
if (children.length > 0) {
|
||||
result.children = children;
|
||||
|
@ -63,5 +63,25 @@ function treeToAST(text: string, n: SyntaxNode): MarkdownTree {
|
|||
}
|
||||
|
||||
export function parse(text: string): MarkdownTree {
|
||||
return treeToAST(text, wikiMarkdownLang.parser.parse(text).topNode);
|
||||
let tree = treeToAST(text, wikiMarkdownLang.parser.parse(text).topNode);
|
||||
// replaceNodesMatching(tree, (n): MarkdownTree | undefined | null => {
|
||||
// if (n.type === "FencedCode") {
|
||||
// let infoN = findNodeMatching(n, (n) => n.type === "CodeInfo");
|
||||
// let language = infoN!.children![0].text;
|
||||
// let textN = findNodeMatching(n, (n) => n.type === "CodeText");
|
||||
// let text = textN!.children![0].text!;
|
||||
//
|
||||
// console.log(language, text);
|
||||
// switch (language) {
|
||||
// case "yaml":
|
||||
// let parsed = StreamLanguage.define(yaml).parser.parse(text);
|
||||
// let subTree = treeToAST(text, parsed.topNode, n.from);
|
||||
// // console.log(JSON.stringify(subTree, null, 2));
|
||||
// subTree.type = "yaml";
|
||||
// return subTree;
|
||||
// }
|
||||
// }
|
||||
// return;
|
||||
// });
|
||||
return tree;
|
||||
}
|
||||
|
|
21
package.json
21
package.json
|
@ -35,7 +35,11 @@
|
|||
"context": "node"
|
||||
},
|
||||
"test": {
|
||||
"source": ["plugs/lib/tree.test.ts", "common/spaces/sync.test.ts"],
|
||||
"source": [
|
||||
"plugs/lib/tree.test.ts",
|
||||
"common/spaces/sync.test.ts"
|
||||
],
|
||||
"includeNodeModules": ["@codemirror/legacy-modes"],
|
||||
"outputFormat": "commonjs",
|
||||
"isLibrary": true,
|
||||
"context": "node"
|
||||
|
@ -45,27 +49,32 @@
|
|||
"@codemirror/closebrackets": "^0.19.1",
|
||||
"@codemirror/collab": "^0.19.0",
|
||||
"@codemirror/commands": "^0.19.8",
|
||||
"@codemirror/highlight": "^0.19.0",
|
||||
"@codemirror/history": "^0.19.2",
|
||||
"@codemirror/lang-javascript": "^0.19.7",
|
||||
"@codemirror/lang-markdown": "^0.19.6",
|
||||
"@codemirror/language": "^0.19.0",
|
||||
"@codemirror/legacy-modes": "^0.19.1",
|
||||
"@codemirror/matchbrackets": "^0.19.4",
|
||||
"@codemirror/search": "^0.19.9",
|
||||
"@codemirror/state": "^0.19.7",
|
||||
"@codemirror/stream-parser": "^0.19.9",
|
||||
"@codemirror/view": "^0.19.42",
|
||||
"@fortawesome/fontawesome-svg-core": "1.3.0",
|
||||
"@fortawesome/free-solid-svg-icons": "6.0.0",
|
||||
"@fortawesome/react-fontawesome": "0.1.17",
|
||||
"@codemirror/highlight": "^0.19.0",
|
||||
"@codemirror/language": "^0.19.0",
|
||||
"@lezer/markdown": "^0.15.0",
|
||||
"@jest/globals": "^27.5.1",
|
||||
"@lezer/markdown": "^0.15.0",
|
||||
"better-sqlite3": "^7.5.0",
|
||||
"body-parser": "^1.19.2",
|
||||
"buffer": "^6.0.3",
|
||||
"cors": "^2.8.5",
|
||||
"dexie": "^3.2.1",
|
||||
"events": "^3.3.0",
|
||||
"express": "^4.17.3",
|
||||
"dexie": "^3.2.1",
|
||||
"fake-indexeddb": "^3.1.7",
|
||||
"jest": "^27.5.1",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"knex": "^1.0.4",
|
||||
"node-cron": "^3.0.0",
|
||||
"node-fetch": "2",
|
||||
|
@ -76,8 +85,6 @@
|
|||
"supertest": "^6.2.2",
|
||||
"vm2": "^3.9.9",
|
||||
"yaml": "^1.10.2",
|
||||
"fake-indexeddb": "^3.1.7",
|
||||
|
||||
"yargs": "^17.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -11,8 +11,8 @@ import fs from "fs";
|
|||
|
||||
class NodeWorkerWrapper implements WorkerLike {
|
||||
onMessage?: (message: any) => Promise<void>;
|
||||
private worker: Worker;
|
||||
ready: Promise<void>;
|
||||
private worker: Worker;
|
||||
|
||||
constructor(worker: Worker) {
|
||||
this.worker = worker;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const { parentPort, workerData } = require("worker_threads");
|
||||
// @ts-ignore
|
||||
let vm2 = `${workerData}/vm2`;
|
||||
const { VM, VMScript } = require(vm2);
|
||||
|
||||
|
@ -15,9 +16,11 @@ let pendingRequests = new Map<
|
|||
|
||||
let syscallReqId = 0;
|
||||
|
||||
// console.log("Here's crypto", crypto);
|
||||
|
||||
let vm = new VM({
|
||||
sandbox: {
|
||||
console: console,
|
||||
console,
|
||||
self: {
|
||||
syscall: (name: string, ...args: any[]) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
"@jest/globals": "^27.5.1",
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/jsonwebtoken": "^8.5.8",
|
||||
"better-sqlite3": "^7.5.0",
|
||||
"body-parser": "^1.19.2",
|
||||
"cors": "^2.8.5",
|
||||
|
@ -49,6 +50,7 @@
|
|||
"express": "^4.17.3",
|
||||
"fake-indexeddb": "^3.1.7",
|
||||
"jest": "^27.5.1",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"knex": "^1.0.4",
|
||||
"node-cron": "^3.0.0",
|
||||
"node-fetch": "2",
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import jwt, { Algorithm } from "jsonwebtoken";
|
||||
import { SysCallMapping } from "../system";
|
||||
|
||||
export function jwtSyscalls(): SysCallMapping {
|
||||
return {
|
||||
"jwt.jwt": (
|
||||
ctx,
|
||||
hexSecret: string,
|
||||
id: string,
|
||||
algorithm: Algorithm,
|
||||
expiry: string,
|
||||
audience: string
|
||||
): string => {
|
||||
return jwt.sign({}, Buffer.from(hexSecret, "hex"), {
|
||||
keyid: id,
|
||||
algorithm: algorithm,
|
||||
expiresIn: expiry,
|
||||
audience: audience,
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1260,6 +1260,13 @@
|
|||
jest-matcher-utils "^27.0.0"
|
||||
pretty-format "^27.0.0"
|
||||
|
||||
"@types/jsonwebtoken@^8.5.8":
|
||||
version "8.5.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.8.tgz#01b39711eb844777b7af1d1f2b4cf22fda1c0c44"
|
||||
integrity sha512-zm6xBQpFDIDM6o9r6HSgDeIcLy82TKWctCXEPbJJcXb5AKmi5BNNdLXneixK4lplX3PqIVcwLBCGE/kAGnlD4A==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/mime@^1":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
|
||||
|
@ -1675,6 +1682,11 @@ bser@2.1.1:
|
|||
dependencies:
|
||||
node-int64 "^0.4.0"
|
||||
|
||||
buffer-equal-constant-time@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
||||
integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
|
||||
|
@ -2243,6 +2255,13 @@ dotenv@^7.0.0:
|
|||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-7.0.0.tgz#a2be3cd52736673206e8a85fb5210eea29628e7c"
|
||||
integrity sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
|
||||
integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
ee-first@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
|
@ -3709,6 +3728,39 @@ json5@^2.1.2, json5@^2.2.0:
|
|||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
|
||||
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
|
||||
|
||||
jsonwebtoken@^8.5.1:
|
||||
version "8.5.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
|
||||
integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
|
||||
dependencies:
|
||||
jws "^3.2.2"
|
||||
lodash.includes "^4.3.0"
|
||||
lodash.isboolean "^3.0.3"
|
||||
lodash.isinteger "^4.0.4"
|
||||
lodash.isnumber "^3.0.3"
|
||||
lodash.isplainobject "^4.0.6"
|
||||
lodash.isstring "^4.0.1"
|
||||
lodash.once "^4.0.0"
|
||||
ms "^2.1.1"
|
||||
semver "^5.6.0"
|
||||
|
||||
jwa@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
|
||||
integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
|
||||
dependencies:
|
||||
buffer-equal-constant-time "1.0.1"
|
||||
ecdsa-sig-formatter "1.0.11"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
jws@^3.2.2:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
|
||||
integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
|
||||
dependencies:
|
||||
jwa "^1.4.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
kleur@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
|
||||
|
@ -3774,11 +3826,46 @@ locate-path@^5.0.0:
|
|||
dependencies:
|
||||
p-locate "^4.1.0"
|
||||
|
||||
lodash.includes@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
|
||||
integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
|
||||
|
||||
lodash.isboolean@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
|
||||
integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
|
||||
|
||||
lodash.isinteger@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
|
||||
integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
|
||||
|
||||
lodash.isnumber@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
|
||||
integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
|
||||
|
||||
lodash.isplainobject@^4.0.6:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
|
||||
integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
|
||||
|
||||
lodash.isstring@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
|
||||
integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
|
||||
|
||||
lodash.memoize@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
|
||||
|
||||
lodash.once@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
|
||||
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
|
||||
|
||||
lodash.uniq@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
|
@ -3914,7 +4001,7 @@ ms@2.1.2:
|
|||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
ms@2.1.3:
|
||||
ms@2.1.3, ms@^2.1.1:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
@ -4754,7 +4841,7 @@ saxes@^5.0.1:
|
|||
dependencies:
|
||||
xmlchars "^2.2.0"
|
||||
|
||||
semver@^5.7.0, semver@^5.7.1:
|
||||
semver@^5.6.0, semver@^5.7.0, semver@^5.7.1:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
|
|
|
@ -60,3 +60,8 @@ functions:
|
|||
path: ./materialized_queries.ts:updateMaterializedQueriesCommand
|
||||
command:
|
||||
name: "Materialized Queries: Update"
|
||||
|
||||
parseCommand:
|
||||
path: ./page.ts:parsePage
|
||||
command:
|
||||
name: Parse Document
|
||||
|
|
|
@ -182,3 +182,7 @@ export async function clearPageIndex(page: string) {
|
|||
console.log("Clearing page index for page", page);
|
||||
await clearPageIndexForPage(page);
|
||||
}
|
||||
|
||||
export async function parsePage() {
|
||||
console.log(await parseMarkdown(await getText()));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
functions:
|
||||
downloadAllPostsCommand:
|
||||
path: "./ghost.ts:downloadAllPostsCommand"
|
||||
command:
|
||||
name: "Ghost: Download Posts"
|
||||
downloadAllPosts:
|
||||
path: "./ghost.ts:downloadAllPosts"
|
||||
env: server
|
||||
publishPostCommand:
|
||||
path: "./ghost.ts:publishPostCommand"
|
||||
command:
|
||||
name: "Ghost: Publish Post"
|
||||
publishPost:
|
||||
path: "./ghost.ts:publishPost"
|
||||
env: server
|
|
@ -0,0 +1,219 @@
|
|||
import { readPage, writePage } from "plugos-silverbullet-syscall/space";
|
||||
import { json } from "plugos-syscall/fetch";
|
||||
import YAML from "yaml";
|
||||
import { invokeFunction } from "plugos-silverbullet-syscall/system";
|
||||
import { getCurrentPage, getText } from "plugos-silverbullet-syscall/editor";
|
||||
|
||||
type Post = {
|
||||
id: string;
|
||||
uuid: string;
|
||||
title: string;
|
||||
slug: string;
|
||||
mobiledoc: string;
|
||||
status: "draft" | "published";
|
||||
visibility: string;
|
||||
created_at: string;
|
||||
upblished_at: string;
|
||||
updated_at: string;
|
||||
tags: Tag[];
|
||||
primary_tag: Tag;
|
||||
url: string;
|
||||
excerpt: string;
|
||||
};
|
||||
|
||||
type Tag = {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
description: string | null;
|
||||
};
|
||||
|
||||
type MobileDoc = {
|
||||
version: string;
|
||||
atoms: any[];
|
||||
cards: Card[];
|
||||
};
|
||||
|
||||
type Card = any[];
|
||||
|
||||
function mobileDocToMarkdown(doc: string): string | null {
|
||||
let mobileDoc = JSON.parse(doc) as MobileDoc;
|
||||
if (mobileDoc.cards.length > 0 && mobileDoc.cards[0][0] === "markdown") {
|
||||
return mobileDoc.cards[0][1].markdown;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function markdownToMobileDoc(text: string): string {
|
||||
return JSON.stringify({
|
||||
version: "0.3.1",
|
||||
atoms: [],
|
||||
cards: [["markdown", { markdown: text }]],
|
||||
markups: [],
|
||||
sections: [
|
||||
[10, 0],
|
||||
[1, "p", []],
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
class GhostAdmin {
|
||||
private token?: string;
|
||||
|
||||
constructor(private url: string, private key: string) {}
|
||||
|
||||
async init() {
|
||||
const [id, secret] = this.key.split(":");
|
||||
|
||||
this.token = await self.syscall(
|
||||
"jwt.jwt",
|
||||
secret,
|
||||
id,
|
||||
"HS256",
|
||||
"5m",
|
||||
"/v3/admin/"
|
||||
);
|
||||
}
|
||||
|
||||
async listPosts(): Promise<Post[]> {
|
||||
let result = await json(
|
||||
`${this.url}/ghost/api/v3/admin/posts?order=published_at+DESC`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Ghost ${this.token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return result.posts;
|
||||
}
|
||||
|
||||
async listMarkdownPosts(): Promise<Post[]> {
|
||||
let markdownPosts: Post[] = [];
|
||||
for (let post of await this.listPosts()) {
|
||||
let mobileDoc = JSON.parse(post.mobiledoc) as MobileDoc;
|
||||
if (mobileDoc.cards.length > 0 && mobileDoc.cards[0][0] === "markdown") {
|
||||
markdownPosts.push(post);
|
||||
}
|
||||
}
|
||||
return markdownPosts;
|
||||
}
|
||||
|
||||
async createPost(post: Partial<Post>): Promise<Post> {
|
||||
let result = await json(`${this.url}/ghost/api/v3/admin/posts`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Ghost ${this.token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
posts: [post],
|
||||
}),
|
||||
});
|
||||
return result.posts[0];
|
||||
}
|
||||
|
||||
async updatePost(post: Partial<Post>): Promise<any> {
|
||||
let oldPost = await json(
|
||||
`${this.url}/ghost/api/v3/admin/posts/${post.id}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Ghost ${this.token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
post.updated_at = oldPost.posts[0].updated_at;
|
||||
let result = await json(`${this.url}/ghost/api/v3/admin/posts/${post.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
Authorization: `Ghost ${this.token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
posts: [post],
|
||||
}),
|
||||
});
|
||||
return result.posts[0];
|
||||
}
|
||||
}
|
||||
|
||||
type GhostConfig = {
|
||||
url: string;
|
||||
adminKey: string;
|
||||
pagePrefix: string;
|
||||
};
|
||||
|
||||
function postToMarkdown(post: Post): string {
|
||||
let text = mobileDocToMarkdown(post.mobiledoc);
|
||||
return `<!-- #ghost-id: ${post.id} -->\n# ${post.title}\n${text}`;
|
||||
}
|
||||
|
||||
const publishedPostRegex =
|
||||
/<!-- #ghost-id:\s*(\w+)\s*-->\n#\s*([^\n]+)\n([^$]+)$/;
|
||||
const newPostRegex = /#\s*([^\n]+)\n([^$]+)$/;
|
||||
|
||||
function markdownToPost(text: string): Partial<Post> {
|
||||
let match = publishedPostRegex.exec(text);
|
||||
if (match) {
|
||||
let [, id, title, content] = match;
|
||||
return {
|
||||
id,
|
||||
title,
|
||||
mobiledoc: markdownToMobileDoc(content),
|
||||
};
|
||||
}
|
||||
match = newPostRegex.exec(text);
|
||||
if (match) {
|
||||
let [, title, content] = match;
|
||||
return {
|
||||
title,
|
||||
status: "draft",
|
||||
mobiledoc: markdownToMobileDoc(content),
|
||||
};
|
||||
}
|
||||
throw Error("Not a valid ghost post");
|
||||
}
|
||||
|
||||
async function getConfig(): Promise<GhostConfig> {
|
||||
let configPage = await readPage("ghost-config");
|
||||
return YAML.parse(configPage.text) as GhostConfig;
|
||||
}
|
||||
|
||||
export async function downloadAllPostsCommand() {
|
||||
await invokeFunction("server", "downloadAllPosts");
|
||||
}
|
||||
export async function downloadAllPosts() {
|
||||
let config = await getConfig();
|
||||
let admin = new GhostAdmin(config.url, config.adminKey);
|
||||
await admin.init();
|
||||
let allPosts = await admin.listMarkdownPosts();
|
||||
for (let post of allPosts) {
|
||||
let text = mobileDocToMarkdown(post.mobiledoc);
|
||||
text = `<!-- #ghost-id: ${post.id} -->\n# ${post.title}\n${text}`;
|
||||
await writePage(`${config.pagePrefix}${post.slug}`, text);
|
||||
}
|
||||
}
|
||||
export async function publishPostCommand() {
|
||||
await invokeFunction(
|
||||
"server",
|
||||
"publishPost",
|
||||
await getCurrentPage(),
|
||||
await getText()
|
||||
);
|
||||
}
|
||||
|
||||
export async function publishPost(name: string, text: string) {
|
||||
let config = await getConfig();
|
||||
let admin = new GhostAdmin(config.url, config.adminKey);
|
||||
await admin.init();
|
||||
let post = markdownToPost(text);
|
||||
post.slug = name.substring(config.pagePrefix.length);
|
||||
if (post.id) {
|
||||
await admin.updatePost(post);
|
||||
} else {
|
||||
let newPost = await admin.createPost(post);
|
||||
text = `<!-- #ghost-id: ${newPost.id} -->\n${text}`;
|
||||
await writePage(name, text);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,14 @@
|
|||
import { expect, test } from "@jest/globals";
|
||||
import { parse } from "../../common/tree";
|
||||
import { addParentPointers, collectNodesMatching, findParentMatching, nodeAtPos, renderMarkdown } from "./tree";
|
||||
import {
|
||||
addParentPointers,
|
||||
collectNodesMatching,
|
||||
findParentMatching,
|
||||
nodeAtPos,
|
||||
removeParentPointers,
|
||||
renderMarkdown,
|
||||
replaceNodesMatching
|
||||
} from "./tree";
|
||||
|
||||
const mdTest1 = `
|
||||
# Heading
|
||||
|
@ -31,6 +39,12 @@ Hello
|
|||
|
||||
Sup`;
|
||||
|
||||
const mdTest3 = `
|
||||
\`\`\`yaml
|
||||
name: something
|
||||
\`\`\`
|
||||
`;
|
||||
|
||||
test("Run a Node sandbox", async () => {
|
||||
let mdTree = parse(mdTest1);
|
||||
addParentPointers(mdTree);
|
||||
|
@ -47,6 +61,15 @@ test("Run a Node sandbox", async () => {
|
|||
// Render back into markdown should be equivalent
|
||||
expect(renderMarkdown(mdTree)).toBe(mdTest1);
|
||||
|
||||
let mdTree2 = parse(mdTest2);
|
||||
console.log(JSON.stringify(mdTree2, null, 2));
|
||||
removeParentPointers(mdTree);
|
||||
replaceNodesMatching(mdTree, (n) => {
|
||||
if (n.type === "Task") {
|
||||
return {
|
||||
type: "Tosk",
|
||||
};
|
||||
}
|
||||
});
|
||||
console.log(JSON.stringify(mdTree, null, 2));
|
||||
let mdTree3 = parse(mdTest3);
|
||||
console.log(JSON.stringify(mdTree3, null, 2));
|
||||
});
|
||||
|
|
|
@ -62,22 +62,20 @@ export function replaceNodesMatching(
|
|||
mdTree: MarkdownTree,
|
||||
substituteFn: (mdTree: MarkdownTree) => MarkdownTree | null | undefined
|
||||
) {
|
||||
let subst = substituteFn(mdTree);
|
||||
if (subst !== undefined) {
|
||||
if (!mdTree.parent) {
|
||||
throw Error("Need parent pointers for this");
|
||||
}
|
||||
let parentChildren = mdTree.parent.children!;
|
||||
let pos = parentChildren.indexOf(mdTree);
|
||||
if (subst) {
|
||||
parentChildren.splice(pos, 1, subst);
|
||||
} else {
|
||||
// null = delete
|
||||
parentChildren.splice(pos, 1);
|
||||
}
|
||||
} else if (mdTree.children) {
|
||||
if (mdTree.children) {
|
||||
for (let child of mdTree.children) {
|
||||
replaceNodesMatching(child, substituteFn);
|
||||
let subst = substituteFn(child);
|
||||
if (subst !== undefined) {
|
||||
let pos = mdTree.children.indexOf(child);
|
||||
if (subst) {
|
||||
mdTree.children.splice(pos, 1, subst);
|
||||
} else {
|
||||
// null = delete
|
||||
mdTree.children.splice(pos, 1);
|
||||
}
|
||||
} else {
|
||||
replaceNodesMatching(child, substituteFn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@jest/globals": "^27.5.1",
|
||||
"@types/yaml": "^1.9.7",
|
||||
"plugos-silverbullet-syscall": "file:../plugos-silverbullet-syscall",
|
||||
"plugos-syscall": "file:../plugos-syscall"
|
||||
"plugos-syscall": "file:../plugos-syscall",
|
||||
"yaml": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ import { EventedSpacePrimitives } from "../common/spaces/evented_space_primitive
|
|||
import { Space } from "../common/spaces/space";
|
||||
import { safeRun } from "../webapp/util";
|
||||
import { createSandbox } from "../plugos/environments/node_sandbox";
|
||||
import { jwtSyscalls } from "../plugos/syscalls/jwt";
|
||||
import { fetchSyscalls } from "../plugos/syscalls/fetch.node";
|
||||
|
||||
export class ExpressServer {
|
||||
app: Express;
|
||||
|
@ -65,6 +67,8 @@ export class ExpressServer {
|
|||
system.registerSyscalls([], spaceSyscalls(this.space));
|
||||
system.registerSyscalls([], eventSyscalls(this.eventHook));
|
||||
system.registerSyscalls([], markdownSyscalls());
|
||||
system.registerSyscalls([], fetchSyscalls());
|
||||
system.registerSyscalls([], jwtSyscalls());
|
||||
system.addHook(new EndpointHook(app, "/_/"));
|
||||
|
||||
this.space.on({
|
||||
|
@ -220,7 +224,7 @@ export class ExpressServer {
|
|||
return res.send(`Plug ${plugName} not found`);
|
||||
}
|
||||
try {
|
||||
console.log("Invoking", name, "with args", args);
|
||||
console.log("Invoking", name);
|
||||
const result = await plug.invoke(name, args);
|
||||
res.status(200);
|
||||
res.send(result);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"include": ["webapp/**/*", "server/**/*", "plugos/**/*", "plugs/**/*"],
|
||||
"include": ["webapp/**/*", "server/**/*", "plugos/**/*", "plugs/**/*", "common/**/*"],
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"strict": true,
|
||||
|
|
|
@ -33,15 +33,15 @@ export function TopBar({
|
|||
<FontAwesomeIcon icon={faFileLines} />
|
||||
</span>
|
||||
<span className="current-page">{prettyName(pageName)}</span>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
// @ts-ignore
|
||||
window.syncer();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
Sync
|
||||
</button>
|
||||
{/*<button*/}
|
||||
{/* onClick={(e) => {*/}
|
||||
{/* // @ts-ignore*/}
|
||||
{/* window.syncer();*/}
|
||||
{/* e.stopPropagation();*/}
|
||||
{/* }}*/}
|
||||
{/*>*/}
|
||||
{/* Sync*/}
|
||||
{/*</button>*/}
|
||||
{notifications.length > 0 && (
|
||||
<div className="status">
|
||||
{notifications.map((notification) => (
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
import { styleTags, tags as t } from "@codemirror/highlight";
|
||||
import { BlockContext, LeafBlock, LeafBlockParser, MarkdownConfig, TaskList } from "@lezer/markdown";
|
||||
import { commonmark, mkLang } from "./markdown/markdown";
|
||||
import { BlockContext, LeafBlock, LeafBlockParser, MarkdownConfig, parseCode, TaskList } from "@lezer/markdown";
|
||||
import { commonmark, getCodeParser, mkLang } from "./markdown/markdown";
|
||||
import * as ct from "./customtags";
|
||||
import { LanguageDescription, LanguageSupport } from "@codemirror/language";
|
||||
import { StreamLanguage } from "@codemirror/stream-parser";
|
||||
import { yaml } from "@codemirror/legacy-modes/mode/yaml";
|
||||
import { javascriptLanguage } from "@codemirror/lang-javascript";
|
||||
|
||||
export const pageLinkRegexPrefix = /^\[\[([\w\s\/:,\.@\-]+)\]\]/;
|
||||
|
||||
|
@ -126,6 +130,7 @@ const TagLink: MarkdownConfig = {
|
|||
},
|
||||
],
|
||||
};
|
||||
|
||||
const WikiMarkdown = commonmark.configure([
|
||||
WikiLink,
|
||||
AtMention,
|
||||
|
@ -133,6 +138,19 @@ const WikiMarkdown = commonmark.configure([
|
|||
TaskList,
|
||||
UnmarkedUrl,
|
||||
Comment,
|
||||
parseCode({
|
||||
codeParser: getCodeParser([
|
||||
LanguageDescription.of({
|
||||
name: "yaml",
|
||||
support: new LanguageSupport(StreamLanguage.define(yaml)),
|
||||
}),
|
||||
LanguageDescription.of({
|
||||
name: "javascript",
|
||||
alias: ["js"],
|
||||
support: new LanguageSupport(javascriptLanguage),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
{
|
||||
props: [
|
||||
styleTags({
|
||||
|
|
114
yarn.lock
114
yarn.lock
|
@ -402,6 +402,19 @@
|
|||
"@codemirror/view" "^0.19.0"
|
||||
"@lezer/javascript" "^0.15.1"
|
||||
|
||||
"@codemirror/lang-javascript@^0.19.7":
|
||||
version "0.19.7"
|
||||
resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-0.19.7.tgz#84581ef6abf2a16d78f017ffc96c2d6227de5eb5"
|
||||
integrity sha512-DL9f3JLqOEHH9cIwEqqjnP5bkjdVXeECksLtV+/MbPm+l4H+AG+PkwZaJQ2oR1GfPZKh8MVSIE94aGWNkJP8WQ==
|
||||
dependencies:
|
||||
"@codemirror/autocomplete" "^0.19.0"
|
||||
"@codemirror/highlight" "^0.19.7"
|
||||
"@codemirror/language" "^0.19.0"
|
||||
"@codemirror/lint" "^0.19.0"
|
||||
"@codemirror/state" "^0.19.0"
|
||||
"@codemirror/view" "^0.19.0"
|
||||
"@lezer/javascript" "^0.15.1"
|
||||
|
||||
"@codemirror/lang-markdown@^0.19.6":
|
||||
version "0.19.6"
|
||||
resolved "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-0.19.6.tgz"
|
||||
|
@ -426,6 +439,13 @@
|
|||
"@lezer/common" "^0.15.5"
|
||||
"@lezer/lr" "^0.15.0"
|
||||
|
||||
"@codemirror/legacy-modes@^0.19.1":
|
||||
version "0.19.1"
|
||||
resolved "https://registry.yarnpkg.com/@codemirror/legacy-modes/-/legacy-modes-0.19.1.tgz#7dc3b5df1842060648f75764ab6919fcfce3ea1a"
|
||||
integrity sha512-vYPLsD/ON+3SXhlGj9Qb3fpFNNU3Ya/AtDiv/g3OyqVzhh5vs5rAnOvk8xopGWRwppdhlNPD9VyXjiOmZUQtmQ==
|
||||
dependencies:
|
||||
"@codemirror/stream-parser" "^0.19.0"
|
||||
|
||||
"@codemirror/lint@^0.19.0":
|
||||
version "0.19.6"
|
||||
resolved "https://registry.npmjs.org/@codemirror/lint/-/lint-0.19.6.tgz"
|
||||
|
@ -483,6 +503,18 @@
|
|||
dependencies:
|
||||
"@codemirror/text" "^0.19.0"
|
||||
|
||||
"@codemirror/stream-parser@^0.19.0", "@codemirror/stream-parser@^0.19.9":
|
||||
version "0.19.9"
|
||||
resolved "https://registry.yarnpkg.com/@codemirror/stream-parser/-/stream-parser-0.19.9.tgz#34955ea91a8047cf72abebd5ce28f0d332aeca48"
|
||||
integrity sha512-WTmkEFSRCetpk8xIOvV2yyXdZs3DgYckM0IP7eFi4ewlxWnJO/H4BeJZLs4wQaydWsAqTQoDyIwNH1BCzK5LUQ==
|
||||
dependencies:
|
||||
"@codemirror/highlight" "^0.19.0"
|
||||
"@codemirror/language" "^0.19.0"
|
||||
"@codemirror/state" "^0.19.0"
|
||||
"@codemirror/text" "^0.19.0"
|
||||
"@lezer/common" "^0.15.0"
|
||||
"@lezer/lr" "^0.15.0"
|
||||
|
||||
"@codemirror/text@^0.19.0", "@codemirror/text@^0.19.2", "@codemirror/text@^0.19.6":
|
||||
version "0.19.6"
|
||||
resolved "https://registry.npmjs.org/@codemirror/text/-/text-0.19.6.tgz"
|
||||
|
@ -1995,6 +2027,11 @@ bser@2.1.1:
|
|||
dependencies:
|
||||
node-int64 "^0.4.0"
|
||||
|
||||
buffer-equal-constant-time@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
||||
integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz"
|
||||
|
@ -2661,6 +2698,13 @@ duplexer3@^0.1.4:
|
|||
resolved "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz"
|
||||
integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
|
||||
integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
ee-first@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz"
|
||||
|
@ -4106,6 +4150,39 @@ json5@^2.1.2, json5@^2.2.0:
|
|||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
|
||||
jsonwebtoken@^8.5.1:
|
||||
version "8.5.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
|
||||
integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
|
||||
dependencies:
|
||||
jws "^3.2.2"
|
||||
lodash.includes "^4.3.0"
|
||||
lodash.isboolean "^3.0.3"
|
||||
lodash.isinteger "^4.0.4"
|
||||
lodash.isnumber "^3.0.3"
|
||||
lodash.isplainobject "^4.0.6"
|
||||
lodash.isstring "^4.0.1"
|
||||
lodash.once "^4.0.0"
|
||||
ms "^2.1.1"
|
||||
semver "^5.6.0"
|
||||
|
||||
jwa@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
|
||||
integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
|
||||
dependencies:
|
||||
buffer-equal-constant-time "1.0.1"
|
||||
ecdsa-sig-formatter "1.0.11"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
jws@^3.2.2:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
|
||||
integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
|
||||
dependencies:
|
||||
jwa "^1.4.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
keyv@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz"
|
||||
|
@ -4185,11 +4262,46 @@ locate-path@^5.0.0:
|
|||
dependencies:
|
||||
p-locate "^4.1.0"
|
||||
|
||||
lodash.includes@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
|
||||
integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
|
||||
|
||||
lodash.isboolean@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
|
||||
integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
|
||||
|
||||
lodash.isinteger@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
|
||||
integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
|
||||
|
||||
lodash.isnumber@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
|
||||
integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
|
||||
|
||||
lodash.isplainobject@^4.0.6:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
|
||||
integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
|
||||
|
||||
lodash.isstring@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
|
||||
integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
|
||||
|
||||
lodash.memoize@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz"
|
||||
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
|
||||
|
||||
lodash.once@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
|
||||
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
|
||||
|
||||
lodash.uniq@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz"
|
||||
|
@ -5319,7 +5431,7 @@ semver-diff@^3.1.1:
|
|||
dependencies:
|
||||
semver "^6.3.0"
|
||||
|
||||
semver@^5.7.0, semver@^5.7.1:
|
||||
semver@^5.6.0, semver@^5.7.0, semver@^5.7.1:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
|
|
Loading…
Reference in New Issue