diff --git a/package-lock.json b/package-lock.json index 9a5ea084..50fee5f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -84,7 +84,9 @@ "webpack": "^5.65.0", "webpack-bundle-analyzer": "^4.5.0", "webpack-cli": "^4.9.1", - "webpack-dev-server": "^4.6.0" + "webpack-dev-server": "^4.6.0", + "yaml": "^1.10.2", + "yawn-yaml": "^1.5.0" }, "engines": { "vscode": "^1.63.0" @@ -9263,6 +9265,23 @@ "engines": { "node": ">= 6" } + }, + "node_modules/yaml-js": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/yaml-js/-/yaml-js-0.1.5.tgz", + "integrity": "sha1-oBNpAQs1WNiq7SOUYV39B4D9j6w=", + "dev": true + }, + "node_modules/yawn-yaml": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yawn-yaml/-/yawn-yaml-1.5.0.tgz", + "integrity": "sha512-sH2zX9K1QiWhWh9U19pye660qlzrEAd5c4ebw/6lqz17LZw7xYi7nqXlBoVLVtc2FZFXDKiJIsvVcKGYbLVyFQ==", + "dev": true, + "dependencies": { + "js-yaml": "^3.4.2", + "lodash": "^4.17.11", + "yaml-js": "^0.1.3" + } } }, "dependencies": { @@ -16268,6 +16287,23 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true + }, + "yaml-js": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/yaml-js/-/yaml-js-0.1.5.tgz", + "integrity": "sha1-oBNpAQs1WNiq7SOUYV39B4D9j6w=", + "dev": true + }, + "yawn-yaml": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yawn-yaml/-/yawn-yaml-1.5.0.tgz", + "integrity": "sha512-sH2zX9K1QiWhWh9U19pye660qlzrEAd5c4ebw/6lqz17LZw7xYi7nqXlBoVLVtc2FZFXDKiJIsvVcKGYbLVyFQ==", + "dev": true, + "requires": { + "js-yaml": "^3.4.2", + "lodash": "^4.17.11", + "yaml-js": "^0.1.3" + } } } } diff --git a/package.json b/package.json index 59b3903f..b283746f 100644 --- a/package.json +++ b/package.json @@ -702,7 +702,10 @@ "$ref": "#contenttypefield" }, "blockType": { - "type": ["string", "array"], + "type": [ + "string", + "array" + ], "default": "", "description": "The ID(s) of your data type(s) defined in the `frontMatter.data.types` setting", "items": { @@ -1508,7 +1511,9 @@ "webpack": "^5.65.0", "webpack-bundle-analyzer": "^4.5.0", "webpack-cli": "^4.9.1", - "webpack-dev-server": "^4.6.0" + "webpack-dev-server": "^4.6.0", + "yaml": "^1.10.2", + "yawn-yaml": "^1.5.0" }, "dependencies": { "node-fetch": "^2.6.7" diff --git a/src/panelWebView/components/Metadata.tsx b/src/panelWebView/components/Metadata.tsx index 468035b9..d197ee8a 100644 --- a/src/panelWebView/components/Metadata.tsx +++ b/src/panelWebView/components/Metadata.tsx @@ -107,8 +107,6 @@ const Metadata: React.FunctionComponent = ({settings, metadata, } else if (field.type === 'string') { const textValue = parent[field.name]; - console.log(textValue, parent, field) - let limit = -1; if (field.name === 'title') { limit = settings?.seo.title; diff --git a/src/parsers/FrontMatterParser.ts b/src/parsers/FrontMatterParser.ts index 155678d4..b26a1b4d 100644 --- a/src/parsers/FrontMatterParser.ts +++ b/src/parsers/FrontMatterParser.ts @@ -14,9 +14,11 @@ export interface ParsedFrontMatter { } export class FrontMatterParser { + public static currentContent: string | null = null; public static fromFile(content: string): ParsedFrontMatter { const format = getFormatOpts(this.getLanguage()); + FrontMatterParser.currentContent = content; const result = matter(content, { ...Engines, ...format }); // in the absent of a body when serializing an entry we use an empty one // when calling `toFile`, so we don't want to add it when parsing. diff --git a/src/parsers/ParserEngines.ts b/src/parsers/ParserEngines.ts index ab57f80c..24f2b0dc 100644 --- a/src/parsers/ParserEngines.ts +++ b/src/parsers/ParserEngines.ts @@ -1,5 +1,6 @@ +import * as yaml from 'yaml'; import * as toml from '@iarna/toml'; -import { Format } from '.'; +import { Format, FrontMatterParser } from '.'; export const getFormatOpts = (format: string): Format => { const formats: { [prop: string]: Format} = { @@ -20,6 +21,82 @@ export const Engines = { stringify: (value: any) => { return toml.stringify(value); } + }, + yaml: { + parse: (value: string) => { + return yaml.parse(value); + }, + stringify: (obj: any, options?: any) => { + // Do our own parsing to keep the comments + if (FrontMatterParser.currentContent) { + const originalContent = FrontMatterParser.currentContent; + FrontMatterParser.currentContent = null; + + const frontMatter = getMatter(originalContent); + if (frontMatter) { + const docYaml = yaml.parseDocument(frontMatter); + + // Update all the new values + for (const key in obj) { + docYaml.set(key, obj[key]); + } + + // Check if there are values to remove + for (const key in docYaml.toJSON()) { + if (!obj[key]) { + docYaml.delete(key); + } + } + + return docYaml.toString(); + } + } + + return yaml.stringify(obj, options); + } } } -} \ No newline at end of file +} + +/** + * Retrieve the front matter from the content + * @param value + * @returns + */ +const getMatter = (value: string): string | null => { + const open = "---"; + const close = '\n' + "---"; + + let str = value; + + // get the length of the opening delimiter + const openLen = open.length; + if (!startsWith(str, open, openLen)) { + return null; + } + + // if the next character after the opening delimiter is + // a character from the delimiter, then it's not a front- + // matter delimiter + if (str.charAt(openLen) === open.slice(-1)) { + return null; + } + + // strip the opening delimiter + str = str.slice(openLen); + const len = str.length; + + // get the index of the closing delimiter + let closeIndex = str.indexOf(close); + if (closeIndex === -1) { + closeIndex = len; + } + + // get the raw front-matter block + return str.slice(0, closeIndex); +} + +const startsWith = (str: string, substr: string, len: number) => { + if (typeof len !== 'number') len = substr.length; + return str.slice(0, len) === substr; +}; \ No newline at end of file