removed grey-matter dependency

This commit is contained in:
Orion Reed 2023-08-13 14:25:39 +01:00
parent 95ab1b472d
commit b73865ddae
14 changed files with 10 additions and 737 deletions

View File

@ -1,51 +0,0 @@
# Simple workflow for deploying static content to GitHub Pages
name: Deploy to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ['main']
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow one concurrent deployment
concurrency:
group: 'pages'
cancel-in-progress: true
jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Node
uses: actions/setup-node@v3
with:
node-version: 18
cache: 'npm'
- name: Install dependencies
run: npm install
- name: Build
run: npm run build
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
# Upload dist repository
path: './dist'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1

View File

@ -1,104 +0,0 @@
/**
* Takes a string or object with `content` property, extracts
* and parses front-matter from the string, then returns an object
* with `data`, `content` and other [useful properties](#returned-object).
*
* @param {Object|String} `input` String, or object with `content` string
* @param {Object} `options`
* @return {Object}
* @api public
*/
declare function matter<
I extends matter.Input,
O extends matter.GrayMatterOption<I, O>,
>(input: I | { content: I }, options?: O): matter.GrayMatterFile<I>
declare namespace matter {
type Input = string
interface GrayMatterOption<
I extends Input,
O extends GrayMatterOption<I, O>,
> {
parser?: () => void
eval?: boolean
excerpt?: boolean | ((input: I, options: O) => string)
excerpt_separator?: string
engines?: {
[index: string]:
| ((input: string) => object)
| {
parse: (input: string) => object
stringify?: (data: object) => string
}
}
language?: string
delimiters?: string | [string, string]
}
interface GrayMatterFile<I extends Input> {
data: { [key: string]: any }
content: string
excerpt?: string
orig: I
language: string
matter: string
stringify(lang: string): string
}
/**
* Stringify an object to YAML or the specified language, and
* append it to the given string. By default, only YAML and JSON
* can be stringified. See the [engines](#engines) section to learn
* how to stringify other languages.
*
* @param {String|Object} `file` The content string to append to stringified front-matter, or a file object with `file.content` string.
* @param {Object} `data` Front matter to stringify.
* @param {Object} `options` [Options](#options) to pass to gray-matter and [js-yaml].
* @return {String} Returns a string created by wrapping stringified yaml with delimiters, and appending that to the given string.
*/
export function stringify<O extends GrayMatterOption<string, O>>(
file: string | { content: string },
data: object,
options?: GrayMatterOption<string, O>,
): string
/**
* Synchronously read a file from the file system and parse
* front matter. Returns the same object as the [main function](#matter).
*
* ```js
* var file = matter.read('./content/blog-post.md');
* ```
* @param {String} `filepath` file path of the file to read.
* @param {Object} `options` [Options](#options) to pass to gray-matter.
* @return {Object} Returns [an object](#returned-object) with `data` and `content`
*/
export function read<O extends GrayMatterOption<string, O>>(
fp: string,
options?: GrayMatterOption<string, O>,
): matter.GrayMatterFile<string>
/**
* Returns true if the given `string` has front matter.
* @param {String} `string`
* @param {Object} `options`
* @return {Boolean} True if front matter exists.
*/
export function test<O extends matter.GrayMatterOption<string, O>>(
str: string,
options?: GrayMatterOption<string, O>,
): boolean
/**
* Detect the language to use, if one is defined after the
* first front-matter delimiter.
* @param {String} `string`
* @param {Object} `options`
* @return {Object} Object with `raw` (actual language string), and `name`, the language with whitespace trimmed
*/
export function language<O extends matter.GrayMatterOption<string, O>>(
str: string,
options?: GrayMatterOption<string, O>,
): { name: string; raw: string }
}
export = matter

View File

@ -1,213 +0,0 @@
import fs from 'fs';
import sections from 'section-matter';
import defaults from './lib/defaults';
import stringify from './lib/stringify';
import excerpt from './lib/excerpt';
import engines from './lib/engines';
import toFile from './lib/to-file';
import parse from './lib/parse';
import * as utils from './lib/utils';
/**
* Takes a string or object with `content` property, extracts
* and parses front-matter from the string, then returns an object
* with `data`, `content` and other [useful properties](#returned-object).
*
* @param {Object|String} `input` String, or object with `content` string
* @param {Object} `options`
* @return {Object}
* @api public
*/
export default function matter(input, options) {
if (input === '') {
return { data: {}, content: input, excerpt: '', orig: input };
}
let file = toFile(input);
const cached = matter.cache[file.content];
if (!options) {
if (cached) {
file = Object.assign({}, cached);
file.orig = cached.orig;
return file;
}
// only cache if there are no options passed. if we cache when options
// are passed, we would need to also cache options values, which would
// negate any performance benefits of caching
matter.cache[file.content] = file;
}
return parseMatter(file, options);
}
/**
* Parse front matter
*/
function parseMatter(file, options) {
const opts = defaults(options);
const open = opts.delimiters[0];
const close = '\n' + opts.delimiters[1];
let str = file.content;
if (opts.language) {
file.language = opts.language;
}
// get the length of the opening delimiter
const openLen = open.length;
if (!utils.startsWith(str, open, openLen)) {
excerpt(file, opts);
return file;
}
// 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 file;
}
// strip the opening delimiter
str = str.slice(openLen);
const len = str.length;
// use the language defined after first delimiter, if it exists
const language = matter.language(str, opts);
if (language.name) {
file.language = language.name;
str = str.slice(language.raw.length);
}
// get the index of the closing delimiter
let closeIndex = str.indexOf(close);
if (closeIndex === -1) {
closeIndex = len;
}
// get the raw front-matter block
file.matter = str.slice(0, closeIndex);
const block = file.matter.replace(/^\s*#[^\n]+/gm, '').trim();
if (block === '') {
file.isEmpty = true;
file.empty = file.content;
file.data = {};
} else {
// create file.data by parsing the raw file.matter block
file.data = parse(file.language, file.matter, opts);
}
// update file.content
if (closeIndex === len) {
file.content = '';
} else {
file.content = str.slice(closeIndex + close.length);
if (file.content[0] === '\r') {
file.content = file.content.slice(1);
}
if (file.content[0] === '\n') {
file.content = file.content.slice(1);
}
}
excerpt(file, opts);
if (opts.sections === true || typeof opts.section === 'function') {
sections(file, opts.section);
}
return file;
}
/**
* Expose engines
*/
matter.engines = engines;
/**
* Stringify an object to YAML or the specified language, and
* append it to the given string. By default, only YAML and JSON
* can be stringified. See the [engines](#engines) section to learn
* how to stringify other languages.
*
* @param {String|Object} `file` The content string to append to stringified front-matter, or a file object with `file.content` string.
* @param {Object} `data` Front matter to stringify.
* @param {Object} `options` [Options](#options) to pass to gray-matter and [js-yaml].
* @return {String} Returns a string created by wrapping stringified yaml with delimiters, and appending that to the given string.
* @api public
*/
matter.stringify = function(file, data, options) {
if (typeof file === 'string') file = matter(file, options);
return stringify(file, data, options);
};
/**
* Synchronously read a file from the file system and parse
* front matter. Returns the same object as the [main function](#matter).
*
* ```js
* const file = matter.read('./content/blog-post.md');
* ```
* @param {String} `filepath` file path of the file to read.
* @param {Object} `options` [Options](#options) to pass to gray-matter.
* @return {Object} Returns [an object](#returned-object) with `data` and `content`
* @api public
*/
matter.read = function(filepath, options) {
const str = fs.readFileSync(filepath, 'utf8');
const file = matter(str, options);
file.path = filepath;
return file;
};
/**
* Returns true if the given `string` has front matter.
* @param {String} `string`
* @param {Object} `options`
* @return {Boolean} True if front matter exists.
* @api public
*/
matter.test = function(str, options) {
return utils.startsWith(str, defaults(options).delimiters[0]);
};
/**
* Detect the language to use, if one is defined after the
* first front-matter delimiter.
* @param {String} `string`
* @param {Object} `options`
* @return {Object} Object with `raw` (actual language string), and `name`, the language with whitespace trimmed
*/
matter.language = function(str, options) {
const opts = defaults(options);
const open = opts.delimiters[0];
if (matter.test(str)) {
str = str.slice(open.length);
}
const language = str.slice(0, str.search(/\r?\n/));
return {
raw: language,
name: language ? language.trim() : ''
};
};
/**
* Expose `matter`
*/
matter.cache = {};
matter.clearCache = function() {
matter.cache = {};
};

View File

@ -1,16 +0,0 @@
import engines from './engines'
import * as utils from './utils'
export default function(options) {
const opts = Object.assign({}, options);
// ensure that delimiters are an array
opts.delimiters = utils.arrayify(opts.delims || opts.delimiters || '---');
if (opts.delimiters.length === 1) {
opts.delimiters.push(opts.delimiters[0]);
}
opts.language = (opts.language || opts.lang || 'yaml').toLowerCase();
opts.engines = Object.assign({}, engines, opts.parsers, opts.engines);
return opts;
};

View File

@ -1,28 +0,0 @@
export default function getEngine(name, options) {
let engine = options.engines[name] || options.engines[aliase(name)];
if (typeof engine === 'undefined') {
throw new Error(`gray-matter engine "${name}" is not registered`);
}
if (typeof engine === 'function') {
engine = { parse: engine };
}
return engine;
};
function aliase(name) {
switch (name.toLowerCase()) {
case 'js':
case 'javascript':
return 'javascript';
case 'coffee':
case 'coffeescript':
case 'cson':
return 'coffee';
case 'yaml':
case 'yml':
return 'yaml';
default: {
return name;
}
}
}

View File

@ -1,53 +0,0 @@
import yaml from 'js-yaml';
/**
* Default engines
*/
const engines = {};
export default engines;
/**
* YAML
*/
engines.yaml = {
parse: yaml.safeLoad.bind(yaml),
stringify: yaml.safeDump.bind(yaml)
};
/**
* JSON
*/
engines.json = {
parse: JSON.parse.bind(JSON),
stringify: function(obj, options) {
const opts = Object.assign({replacer: null, space: 2}, options);
return JSON.stringify(obj, opts.replacer, opts.space);
}
};
/**
* JavaScript
*/
engines.javascript = {
parse: function parse(str, options, wrap) {
/* eslint no-eval: 0 */
try {
if (wrap !== false) {
str = '(function() {\nreturn ' + str.trim() + ';\n}());';
}
return eval(str) || {};
} catch (err) {
if (wrap !== false && /(unexpected|identifier)/i.test(err.message)) {
return parse(str, options, false);
}
throw new SyntaxError(err);
}
},
stringify: function() {
throw new Error('stringifying JavaScript is not supported');
}
};

View File

@ -1,30 +0,0 @@
import defaults from './defaults';
export default function excerpt(file, options) {
const opts = defaults(options);
if (file.data == null) {
file.data = {};
}
if (typeof opts.excerpt === 'function') {
return opts.excerpt(file, opts);
}
const sep = file.data.excerpt_separator || opts.excerpt_separator;
if (sep == null && (opts.excerpt === false || opts.excerpt == null)) {
return file;
}
const delimiter = typeof opts.excerpt === 'string'
? opts.excerpt
: (sep || opts.delimiters[0]);
// if enabled, get the excerpt defined after front-matter
const idx = file.content.indexOf(delimiter);
if (idx !== -1) {
file.excerpt = file.content.slice(0, idx);
}
return file;
};

View File

@ -1,12 +0,0 @@
import getEngine from './engine';
import defaults from './defaults';
export default function parse(language, str, options) {
const opts = defaults(options);
const engine = getEngine(language, opts);
if (typeof engine.parse !== 'function') {
throw new TypeError(`expected "${language}.parse" to be a function`);
}
return engine.parse(str, opts);
};

View File

@ -1,55 +0,0 @@
import typeOf from 'kind-of';
import getEngine from './engine';
import defaults from './defaults';
export default function stringify(file, data, options) {
if (data == null && options == null) {
switch (typeOf(file)) {
case 'object':
data = file.data;
options = {};
break;
case 'string':
return file;
default: {
throw new TypeError('expected file to be a string or object');
}
}
}
const str = file.content;
const opts = defaults(options);
if (data == null) {
if (!opts.data) return file;
data = opts.data;
}
const language = file.language || opts.language;
const engine = getEngine(language, opts);
if (typeof engine.stringify !== 'function') {
throw new TypeError('expected "' + language + '.stringify" to be a function');
}
data = Object.assign({}, file.data, data);
const open = opts.delimiters[0];
const close = opts.delimiters[1];
const matter = engine.stringify(data, options).trim();
let buf = '';
if (matter !== '{}') {
buf = newline(open) + newline(matter) + newline(close);
}
if (typeof file.excerpt === 'string' && file.excerpt !== '') {
if (str.indexOf(file.excerpt.trim()) === -1) {
buf += newline(file.excerpt) + newline(close);
}
}
return buf + newline(str);
};
function newline(str) {
return str.slice(-1) !== '\n' ? str + '\n' : str;
}

View File

@ -1,41 +0,0 @@
import typeOf from 'kind-of';
import stringify from './stringify';
import * as utils from './utils';
/**
* Normalize the given value to ensure an object is returned
* with the expected properties.
*/
export default function toFile(file) {
if (typeOf(file) !== 'object') {
file = { content: file };
}
if (typeOf(file.data) !== 'object') {
file.data = {};
}
// if file was passed as an object, ensure that
// "file.content" is set
if (file.contents && file.content == null) {
file.content = file.contents;
}
// set non-enumerable properties on the file object
utils.define(file, 'language', file.language || '');
utils.define(file, 'matter', file.matter || '');
utils.define(file, 'stringify', function(data, options) {
if (options && options.language) {
file.language = options.language;
}
return stringify(file, data, options);
});
// strip BOM and ensure that "file.content" is a string
file.content = utils.toString(file.content);
file.isEmpty = false;
file.excerpt = '';
return file;
};

View File

@ -1,47 +0,0 @@
import stripBom from 'strip-bom-string'
import typeOf from 'kind-of'
export function define(obj, key, val) {
Reflect.defineProperty(obj, key, {
enumerable: false,
configurable: true,
writable: true,
value: val
});
};
/**
* Returns true if `val` is an object
*/
export function isObject(val) {
return typeOf(val) === 'object';
};
/**
* Cast `val` to a string.
*/
export function toString(input) {
if (typeof input !== 'string') {
throw new TypeError('expected input to be a string');
}
return stripBom(input);
};
/**
* Cast `val` to an array.
*/
export function arrayify(val) {
return val ? (Array.isArray(val) ? val : [val]) : [];
};
/**
* Returns true if `str` starts with `substr`.
*/
export function startsWith(str, substr, len) {
if (typeof len !== 'number') len = substr.length;
return str.slice(0, len) === substr;
};

View File

@ -1,78 +0,0 @@
{
"name": "gray-matter",
"version": "4.0.3",
"author": "Jon Schlinkert (https://github.com/jonschlinkert)",
"type":"module",
"license": "MIT",
"files": [
"gray-matter.d.ts",
"index.js",
"lib"
],
"main": "index.js",
"engines": {
"node": ">=6.0"
},
"scripts": {
"test": "mocha"
},
"dependencies": {
"js-yaml": "^3.13.1",
"kind-of": "^6.0.2",
"section-matter": "^1.0.0",
"strip-bom-string": "^1.0.0"
},
"devDependencies": {
"ansi-green": "^0.1.1",
"benchmarked": "^2.0.0",
"coffeescript": "^2.2.3",
"delimiter-regex": "^2.0.0",
"extend-shallow": "^3.0.2",
"front-matter": "^2.3.0",
"gulp-format-md": "^1.0.0",
"minimist": "^1.2.0",
"mocha": "^6.1.4",
"toml": "^2.3.3",
"vinyl": "^2.1.0",
"write": "^1.0.3"
},
"browser": {
"fs": false
},
"typings": "gray-matter.d.ts",
"eslintConfig": {
"rules": {
"no-console": 0
}
},
"verb": {
"toc": false,
"layout": "default",
"tasks": [
"readme"
],
"plugins": [
"gulp-format-md"
],
"helpers": {
"examples": "./examples/helper.js"
},
"lint": {
"reflinks": true
},
"related": {
"list": [
"assemble",
"metalsmith",
"verb"
]
},
"reflinks": [
"coffe-script",
"generate",
"js-yaml",
"toml",
"update"
]
}
}

View File

@ -14,7 +14,6 @@
"@mantine/hooks": "^6.0.19",
"@preact/signals": "^1.2.1",
"date-fns": "^2.30.0",
"gray-matter": "file:deps/gray-matter",
"jsonlines": "^0.1.1",
"minisearch": "^6.1.0",
"preact": "^10.13.1",

View File

@ -7,12 +7,13 @@ import {
Group,
} from '@mantine/core'
import Markdown from 'markdown-to-jsx'
import matter from 'gray-matter'
import fm from 'front-matter'
import { readingTime } from 'reading-time-estimator'
import { Header } from '@/components/Header'
import { getCurrentUrl } from 'preact-router'
import { useState, useEffect } from 'preact/hooks'
import { friendlyDate } from '@/utils'
import { useTitle } from '@/hooks/useTitle'
const useStyles = createStyles((theme) => ({
title: {
@ -34,7 +35,7 @@ const useStyles = createStyles((theme) => ({
async function getPost(name: string) {
const response = await fetch(`${name}.md?raw`)
return matter(await response.text())
return fm(await response.text())
}
export default function Post() {
@ -57,16 +58,17 @@ export default function Post() {
</>
)
} else {
const readTime = readingTime(post.content).text
const date = friendlyDate(post.data.date)
const location = post.data.location
useTitle(post.attributes.title)
const readTime = readingTime(post.body).text
const date = friendlyDate(post.attributes.date)
const location = post.attributes.location
return (
<>
<Header dark />
<Box mb="lg" bg="red" py="lg">
<Container size="40em">
<Text className={classes.title}>{post.data.title}</Text>
<Text className={classes.subtitle}>{post.data.subtitle}</Text>
<Text className={classes.title}>{post.attributes.title}</Text>
<Text className={classes.subtitle}>{post.attributes.subtitle}</Text>
<Group position="apart">
<Text className={classes.info}>{date}</Text>
<Text className={classes.info}>{location}</Text>
@ -76,7 +78,7 @@ export default function Post() {
</Box>
<Container size="40em">
<TypographyStylesProvider>
<Markdown>{post.content}</Markdown>
<Markdown>{post.body}</Markdown>
</TypographyStylesProvider>
</Container>
</>