From 80b82d739cd80fbfbdc8e2f17d4a5f87397310f2 Mon Sep 17 00:00:00 2001 From: jonschlinkert Date: Fri, 20 Oct 2017 22:01:28 -0400 Subject: [PATCH 01/23] lint --- examples/cache.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/cache.js b/examples/cache.js index 7df47f5..931faa1 100644 --- a/examples/cache.js +++ b/examples/cache.js @@ -1,5 +1,5 @@ // https://github.com/jonschlinkert/gray-matter/issues/43 -var frontMatter = require('gray-matter'); +var frontMatter = require('..'); var docs = [ { From 64ed507307a6ce73e9a7113fa724a2ac1cb6a05d Mon Sep 17 00:00:00 2001 From: jonschlinkert Date: Fri, 20 Oct 2017 22:01:42 -0400 Subject: [PATCH 02/23] 3.1.1 reverts mocha version since it has breaking changes. --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e462841..73eb242 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "gray-matter", "description": "Parse front-matter from a string or file. Fast, reliable and easy to use. Parses YAML front matter by default, but also has support for YAML, JSON, TOML or Coffee Front-Matter, with options to set custom delimiters. Used by metalsmith, assemble, verb and many other projects.", - "version": "3.1.0", + "version": "3.1.1", "homepage": "https://github.com/jonschlinkert/gray-matter", "author": "Jon Schlinkert (https://github.com/jonschlinkert)", "contributors": [ @@ -50,7 +50,7 @@ "front-matter": "^2.2.0", "gulp-format-md": "^1.0.0", "minimist": "^1.2.0", - "mocha": "^4.0.0", + "mocha": "^3.5.3", "toml": "^2.3.3", "vinyl": "^2.1.0", "write": "^1.0.3" From 58a62972d5cbcf6a2c46203173dee3e71693e1e4 Mon Sep 17 00:00:00 2001 From: Ben Wilcox Date: Wed, 8 Nov 2017 23:44:58 -0500 Subject: [PATCH 03/23] Update excerpt documentation and examples Shows how to pass a function to the excerpt option parameter in the .verb README and in the examples folder. --- .verb.md | 52 +++++++++++++++++++++++++++++++++++++++------ examples/excerpt.js | 28 +++++++++++++++++++++--- 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/.verb.md b/.verb.md index 9a39e80..e72511d 100644 --- a/.verb.md +++ b/.verb.md @@ -168,26 +168,66 @@ $ node examples/ ### options.excerpt -**Type**: `Object` +**Type**: `Boolean|Function` **Default**: `undefined` Extract an excerpt that directly follows front-matter, or is the first thing in the string if no front-matter exists. +If set to `excerpt: true`, it will look for the frontmatter delimiter, `---` by default and grab everything leading up to it. + +**Example** + +```js +var file = matter([ + '---', + 'foo: bar', + '---', + 'This is an excerpt.', + '---', + 'This is content' +].join('\n'), {excerpt: true}); +``` + +Results in: + +```js +{ + content: 'This is an excerpt.\n---\nThis is content', + data: { foo: 'bar' }, + excerpt: 'This is an excerpt.\n' +} +``` + +You can also set `excerpt` to a function. This function uses the 'file' and 'options' that were initially passed to gray-matter as parameters, so you can control how the excerpt is extracted from the content. + **Example** ```js -var str = '--\ntitle: Home\n---\nAn excerpt\n---\nOther stuff'; -console.log(matter(str, {excerpt: true})); +// returns the first 4 lines of the contents +function firstFourLines(file, options) { + file.excerpt = file.content.split('\n').slice(0, 4).join(' '); +} + +var file = matter([ + '---', + 'foo: bar', + '---', + 'Only this', + 'will be', + 'in the', + 'excerpt', + 'but not this...' +].join('\n'), {excerpt: firstFourLines}); ``` Results in: ```js { - data: { title: 'Home'}, - excerpt: '\nAn excerpt', - content: '\nAn excerpt\n---\nOther stuff' + content: 'Only this\nwill be\nin the\nexcerpt\nbut not this...', + data: { foo: 'bar' }, + excerpt: 'Only this will be in the excerpt' } ``` diff --git a/examples/excerpt.js b/examples/excerpt.js index 8918a52..f263585 100644 --- a/examples/excerpt.js +++ b/examples/excerpt.js @@ -3,7 +3,8 @@ var matter = require('..'); var fixture = path.join.bind(path, __dirname, 'fixtures'); var magenta = require('ansi-magenta'); -var file = matter([ +// excerpt as a boolean +var file1 = matter([ '---', 'foo: bar', '---', @@ -12,5 +13,26 @@ var file = matter([ 'This is content' ].join('\n'), {excerpt: true}); -console.log(magenta('/* excerpt */')); -console.log(file); +console.log(magenta('/* excerpt: true */')); +console.log(file1); + +// excerpt as a function + +// returns the first 4 lines of the contents +function firstFourLines(file, options) { + file.excerpt = file.content.split('\n').slice(0, 4).join(' '); +} + +var file2 = matter([ +'---', +'foo: bar', +'---', +'Only this', +'will be', +'in the', +'excerpt', +'but not this...' +].join('\n'), {excerpt: firstFourLines }); + +console.log(magenta('/* excerpt: function(file, options) { ... } */')); +console.log(file2); \ No newline at end of file From 167e8468a81da72d2fb51e06e9bb442b9268664b Mon Sep 17 00:00:00 2001 From: Ben Wilcox Date: Fri, 10 Nov 2017 09:18:39 -0500 Subject: [PATCH 04/23] Fix indents --- .verb.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.verb.md b/.verb.md index e72511d..425ecfb 100644 --- a/.verb.md +++ b/.verb.md @@ -193,9 +193,9 @@ Results in: ```js { - content: 'This is an excerpt.\n---\nThis is content', - data: { foo: 'bar' }, - excerpt: 'This is an excerpt.\n' + content: 'This is an excerpt.\n---\nThis is content', + data: { foo: 'bar' }, + excerpt: 'This is an excerpt.\n' } ``` @@ -206,7 +206,7 @@ You can also set `excerpt` to a function. This function uses the 'file' and 'opt ```js // returns the first 4 lines of the contents function firstFourLines(file, options) { - file.excerpt = file.content.split('\n').slice(0, 4).join(' '); + file.excerpt = file.content.split('\n').slice(0, 4).join(' '); } var file = matter([ @@ -225,9 +225,9 @@ Results in: ```js { - content: 'Only this\nwill be\nin the\nexcerpt\nbut not this...', - data: { foo: 'bar' }, - excerpt: 'Only this will be in the excerpt' + content: 'Only this\nwill be\nin the\nexcerpt\nbut not this...', + data: { foo: 'bar' }, + excerpt: 'Only this will be in the excerpt' } ``` From 5d9e7046d459dc0ad10b4747eccd037facb817a5 Mon Sep 17 00:00:00 2001 From: John Chappell Date: Thu, 30 Nov 2017 10:23:40 -0600 Subject: [PATCH 05/23] Lock down coffee-script to remove error being thrown in 1.12.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 73eb242..410c170 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "devDependencies": { "ansi-magenta": "^0.1.1", "benchmarked": "^2.0.0", - "coffee-script": "^1.12.7", + "coffeescript": "1.12.7", "delimiter-regex": "^2.0.0", "front-matter": "^2.2.0", "gulp-format-md": "^1.0.0", From 94a631ff1a3e758375488bbb3f484134cba0ac1b Mon Sep 17 00:00:00 2001 From: John Chappell Date: Thu, 30 Nov 2017 10:30:03 -0600 Subject: [PATCH 06/23] change required package from coffee-script to coffeescript --- examples/coffee.js | 2 +- test/parse-coffee.js | 2 +- test/parse-cson.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/coffee.js b/examples/coffee.js index 57d49d7..446d624 100644 --- a/examples/coffee.js +++ b/examples/coffee.js @@ -1,6 +1,6 @@ var path = require('path'); var matter = require('..'); -var coffee = require('coffee-script'); +var coffee = require('coffeescript); var magenta = require('ansi-magenta'); var fixture = path.join.bind(path, __dirname, 'fixtures'); diff --git a/test/parse-coffee.js b/test/parse-coffee.js index 059946d..03bacfe 100644 --- a/test/parse-coffee.js +++ b/test/parse-coffee.js @@ -12,7 +12,7 @@ var assert = require('assert'); var extend = require('extend-shallow'); var matter = require('../'); var fixture = path.join.bind(path, __dirname, 'fixtures'); -var coffee = require('coffee-script'); +var coffee = require('coffeescript); var defaults = { engines: { coffee: { diff --git a/test/parse-cson.js b/test/parse-cson.js index ed3fa53..33a51b9 100644 --- a/test/parse-cson.js +++ b/test/parse-cson.js @@ -11,7 +11,7 @@ var path = require('path'); var assert = require('assert'); var matter = require('..'); var extend = require('extend-shallow'); -var coffee = require('coffee-script'); +var coffee = require('coffeescript); var fixture = path.join.bind(path, __dirname, 'fixtures'); var defaults = { engines: { From 3a188c6d798f45b68e51d96a142ddc2f227a3b90 Mon Sep 17 00:00:00 2001 From: John Chappell Date: Thu, 30 Nov 2017 10:32:45 -0600 Subject: [PATCH 07/23] Lesson learned. test before pushing. fixed replace of coffeescript. --- examples/coffee.js | 2 +- test/parse-coffee.js | 2 +- test/parse-cson.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/coffee.js b/examples/coffee.js index 446d624..e90aeff 100644 --- a/examples/coffee.js +++ b/examples/coffee.js @@ -1,6 +1,6 @@ var path = require('path'); var matter = require('..'); -var coffee = require('coffeescript); +var coffee = require('coffeescript'); var magenta = require('ansi-magenta'); var fixture = path.join.bind(path, __dirname, 'fixtures'); diff --git a/test/parse-coffee.js b/test/parse-coffee.js index 03bacfe..517bde2 100644 --- a/test/parse-coffee.js +++ b/test/parse-coffee.js @@ -12,7 +12,7 @@ var assert = require('assert'); var extend = require('extend-shallow'); var matter = require('../'); var fixture = path.join.bind(path, __dirname, 'fixtures'); -var coffee = require('coffeescript); +var coffee = require('coffeescript'); var defaults = { engines: { coffee: { diff --git a/test/parse-cson.js b/test/parse-cson.js index 33a51b9..152def5 100644 --- a/test/parse-cson.js +++ b/test/parse-cson.js @@ -11,7 +11,7 @@ var path = require('path'); var assert = require('assert'); var matter = require('..'); var extend = require('extend-shallow'); -var coffee = require('coffeescript); +var coffee = require('coffeescript'); var fixture = path.join.bind(path, __dirname, 'fixtures'); var defaults = { engines: { From 9b63b5fb7cb5f5c2754a8025162930dfcac7a079 Mon Sep 17 00:00:00 2001 From: doowb Date: Sat, 3 Mar 2018 11:36:43 -0500 Subject: [PATCH 08/23] run verb to generate readme --- README.md | 121 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 15c32fc..08b869d 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,7 @@ Then run any of the [examples](./examples) to see how gray-matter works: $ node examples/ ``` +* [cache](examples/cache.js) * [coffee](examples/coffee.js) * [excerpt-separator](examples/excerpt-separator.js) * [excerpt-stringify](examples/excerpt-stringify.js) @@ -251,26 +252,66 @@ Returns true if the given `string` has front matter. ### options.excerpt -**Type**: `Object` +**Type**: `Boolean|Function` **Default**: `undefined` Extract an excerpt that directly follows front-matter, or is the first thing in the string if no front-matter exists. +If set to `excerpt: true`, it will look for the frontmatter delimiter, `---` by default and grab everything leading up to it. + +**Example** + +```js +var file = matter([ + '---', + 'foo: bar', + '---', + 'This is an excerpt.', + '---', + 'This is content' +].join('\n'), {excerpt: true}); +``` + +Results in: + +```js +{ + content: 'This is an excerpt.\n---\nThis is content', + data: { foo: 'bar' }, + excerpt: 'This is an excerpt.\n' +} +``` + +You can also set `excerpt` to a function. This function uses the 'file' and 'options' that were initially passed to gray-matter as parameters, so you can control how the excerpt is extracted from the content. + **Example** ```js -var str = '--\ntitle: Home\n---\nAn excerpt\n---\nOther stuff'; -console.log(matter(str, {excerpt: true})); +// returns the first 4 lines of the contents +function firstFourLines(file, options) { + file.excerpt = file.content.split('\n').slice(0, 4).join(' '); +} + +var file = matter([ + '---', + 'foo: bar', + '---', + 'Only this', + 'will be', + 'in the', + 'excerpt', + 'but not this...' +].join('\n'), {excerpt: firstFourLines}); ``` Results in: ```js { - data: { title: 'Home'}, - excerpt: '\nAn excerpt', - content: '\nAn excerpt\n---\nOther stuff' + content: 'Only this\nwill be\nin the\nexcerpt\nbut not this...', + data: { foo: 'bar' }, + excerpt: 'Only this will be in the excerpt' } ``` @@ -448,26 +489,33 @@ Decrecated, please use [options.engines](#optionsengines) instead. ## About -
-Contributing - -Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). - -
+### Related projects -
-Running Tests +* [assemble](https://www.npmjs.com/package/assemble): Get the rocks out of your socks! Assemble makes you fast at creating web projects… [more](https://github.com/assemble/assemble) | [homepage](https://github.com/assemble/assemble "Get the rocks out of your socks! Assemble makes you fast at creating web projects. Assemble is used by thousands of projects for rapid prototyping, creating themes, scaffolds, boilerplates, e-books, UI components, API documentation, blogs, building websit") +* [metalsmith](https://www.npmjs.com/package/metalsmith): An extremely simple, pluggable static site generator. | [homepage](https://github.com/segmentio/metalsmith#readme "An extremely simple, pluggable static site generator.") +* [verb](https://www.npmjs.com/package/verb): Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used… [more](https://github.com/verbose/verb) | [homepage](https://github.com/verbose/verb "Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used on hundreds of projects of all sizes to generate everything from API docs to readmes.") -Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: +### Contributing -```sh -$ npm install && npm test -``` +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). -
+### Contributors -
-Building docs +| **Commits** | **Contributor** | +| --- | --- | +| 172 | [jonschlinkert](https://github.com/jonschlinkert) | +| 7 | [RobLoach](https://github.com/RobLoach) | +| 5 | [heymind](https://github.com/heymind) | +| 3 | [doowb](https://github.com/doowb) | +| 2 | [reccanti](https://github.com/reccanti) | +| 2 | [onokumus](https://github.com/onokumus) | +| 2 | [moozzyk](https://github.com/moozzyk) | +| 1 | [Ajedi32](https://github.com/Ajedi32) | +| 1 | [caesar](https://github.com/caesar) | +| 1 | [ianstormtaylor](https://github.com/ianstormtaylor) | +| 1 | [zachwhaley](https://github.com/zachwhaley) | + +### Building docs _(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ @@ -477,30 +525,13 @@ To generate the readme, run the following command: $ npm install -g verbose/verb#dev verb-generate-readme && verb ``` -
+### Running tests -### Related projects - -You might also be interested in these projects: - -* [assemble](https://www.npmjs.com/package/assemble): Get the rocks out of your socks! Assemble makes you fast at creating web projects… [more](https://github.com/assemble/assemble) | [homepage](https://github.com/assemble/assemble "Get the rocks out of your socks! Assemble makes you fast at creating web projects. Assemble is used by thousands of projects for rapid prototyping, creating themes, scaffolds, boilerplates, e-books, UI components, API documentation, blogs, building websit") -* [metalsmith](https://www.npmjs.com/package/metalsmith): An extremely simple, pluggable static site generator. | [homepage](https://github.com/segmentio/metalsmith#readme "An extremely simple, pluggable static site generator.") -* [verb](https://www.npmjs.com/package/verb): Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used… [more](https://github.com/verbose/verb) | [homepage](https://github.com/verbose/verb "Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used on hundreds of projects of all sizes to generate everything from API docs to readmes.") - -### Contributors +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: -| **Commits** | **Contributor** | -| --- | --- | -| 163 | [jonschlinkert](https://github.com/jonschlinkert) | -| 7 | [RobLoach](https://github.com/RobLoach) | -| 5 | [heymind](https://github.com/heymind) | -| 2 | [doowb](https://github.com/doowb) | -| 2 | [onokumus](https://github.com/onokumus) | -| 2 | [moozzyk](https://github.com/moozzyk) | -| 1 | [Ajedi32](https://github.com/Ajedi32) | -| 1 | [caesar](https://github.com/caesar) | -| 1 | [ianstormtaylor](https://github.com/ianstormtaylor) | -| 1 | [zachwhaley](https://github.com/zachwhaley) | +```sh +$ npm install && npm test +``` ### Author @@ -511,9 +542,9 @@ You might also be interested in these projects: ### License -Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). +Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert). Released under the [MIT License](LICENSE). *** -_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on October 19, 2017._ \ No newline at end of file +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on March 03, 2018._ \ No newline at end of file From ba30f1366d71d06aaf72b57671baa35f4b2048f5 Mon Sep 17 00:00:00 2001 From: Mihal Malostanidis Date: Sun, 4 Mar 2018 04:03:17 +0200 Subject: [PATCH 09/23] Extend TypeScript declaration Includes descriptions and types --- gray-matter.d.ts | 117 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 108 insertions(+), 9 deletions(-) diff --git a/gray-matter.d.ts b/gray-matter.d.ts index 76f8e04..a9fc520 100644 --- a/gray-matter.d.ts +++ b/gray-matter.d.ts @@ -1,15 +1,114 @@ -declare function matter(str: string, options?: matter.GrayMatterOption): any +/** + * 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). + * + * ```js + * var matter = require('gray-matter'); + * console.log(matter('---\ntitle: Home\n---\nOther stuff')); + * //=> { data: { title: 'Home'}, content: 'Other stuff' } + * ``` + * @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 +>(input: I | { content: I }, options?: O): matter.GrayMatterFile declare namespace matter { - interface GrayMatterOption { - parser?: () => void; - eval?: boolean; - lang?: string; - delims?: string | string[]; + type Input = string | Buffer + interface GrayMatterOption< + I extends Input, + O extends GrayMatterOption + > { + parser?: () => void + eval?: boolean + excerpt?: boolean | ((input: I, options: O) => string) + excerpt_separator?: string + engines?: { + [index: string]: + | ((string) => object) + | { parse: (string) => object; stringify?: (object) => string } + } + language?: string + delimiters?: string | [string, string] } - export function read(fp: string, options?: GrayMatterOption): any; - export function stringify(str: string, data: object, options?: GrayMatterOption): string; - export function test(str: string, options?: GrayMatterOption): string; + interface GrayMatterFile { + data: object + content: string + excrept?: string + orig: Buffer | 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. + * + * ```js + * console.log(matter.stringify('foo bar baz', {title: 'Home'})); + * // results in: + * // --- + * // title: Home + * // --- + * // foo bar baz + * ``` + * @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>( + file: string | { content: string }, + data: object, + options?: GrayMatterOption + ): 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>( + fp: string, + options?: GrayMatterOption + ): matter.GrayMatterFile + + /** + * 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>( + str: string, + options?: GrayMatterOption + ): 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>( + str: string, + options?: GrayMatterOption + ): { name: string; raw: string } } export = matter From da329cd73a8c4b756bb2c33f5e0960cf8a717779 Mon Sep 17 00:00:00 2001 From: Jon Schlinkert Date: Sun, 1 Apr 2018 23:27:24 -0400 Subject: [PATCH 10/23] isempty (#66) - adds support for empty front matter - upgraded to es6 - update docs closes https://github.com/jonschlinkert/gray-matter/issues/65 --- .eslintrc.json | 14 +++ .gitignore | 1 + .travis.yml | 5 +- .verb.md | 35 ++++---- CHANGELOG.md | 21 +++-- LICENSE | 2 +- README.md | 125 ++++++++++++++------------ bower.json | 42 +++++---- examples/cache.js | 20 ----- examples/coffee.js | 21 ++--- examples/excerpt-separator.js | 10 +-- examples/excerpt-stringify.js | 12 ++- examples/excerpt.js | 34 ++++--- examples/fixtures/sections-excerpt.md | 32 +++++++ examples/fixtures/sections.md | 31 +++++++ examples/helper.js | 16 ++-- examples/javascript.js | 11 ++- examples/json-stringify.js | 18 ++-- examples/json.js | 12 ++- examples/restore-empty.js | 16 ++++ examples/sections-excerpt.js | 9 ++ examples/sections.js | 18 ++++ examples/toml.js | 13 ++- examples/yaml-stringify.js | 15 ++-- examples/yaml.js | 7 +- index.js | 95 ++++++++++++-------- lib/defaults.js | 9 +- lib/engine.js | 2 +- lib/engines.js | 7 +- lib/excerpt.js | 15 ++-- lib/parse.js | 8 +- lib/stringify.js | 29 +++--- lib/to-file.js | 52 ++++------- lib/utils.js | 21 ++--- package.json | 27 +++--- test/matter-empty.js | 35 ++++++++ test/matter.js | 14 --- 37 files changed, 487 insertions(+), 367 deletions(-) delete mode 100644 examples/cache.js create mode 100644 examples/fixtures/sections-excerpt.md create mode 100644 examples/fixtures/sections.md create mode 100644 examples/restore-empty.js create mode 100644 examples/sections-excerpt.js create mode 100644 examples/sections.js create mode 100644 test/matter-empty.js diff --git a/.eslintrc.json b/.eslintrc.json index 61e8895..41a5fdc 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,4 +1,9 @@ { + "extends": [ + "eslint:recommended", + "./package.json" + ], + "env": { "browser": false, "es6": true, @@ -6,6 +11,15 @@ "mocha": true }, + "parserOptions":{ + "ecmaVersion": 9, + "sourceType": "module", + "ecmaFeatures": { + "modules": true, + "experimentalObjectRestSpread": true + } + }, + "globals": { "document": false, "navigator": false, diff --git a/.gitignore b/.gitignore index 4bf0a60..f969a2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # always ignore files *.DS_Store .idea +.vscode *.sublime-* # test related, or directories generated by tests diff --git a/.travis.yml b/.travis.yml index 67decb2..1fd107d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,7 @@ os: language: node_js node_js: - node + - '9' - '8' - '7' - '6' - - '5' - - '4' - - '0.12' - - '0.10' diff --git a/.verb.md b/.verb.md index 425ecfb..05a92b5 100644 --- a/.verb.md +++ b/.verb.md @@ -10,9 +10,9 @@ Please see the [changelog](CHANGELOG.md) to learn about breaking changes that we Add the HTML in the following example to `example.html`, then add the following code to `example.js` and run `$ node example` (without the `$`): ```js -var fs = require('fs'); -var matter = require('gray-matter'); -var str = fs.readFileSync('example.html', 'utf8'); +const fs = require('fs'); +const matter = require('gray-matter'); +const str = fs.readFileSync('example.html', 'utf8'); console.log(matter(str)); ``` @@ -72,10 +72,10 @@ Some libraries met most of the requirements, but _none met all of them_. * Have no problem with complex content, including **non-front-matter** fenced code blocks that contain examples of YAML front matter. Other parsers fail on this. * Support stringifying back to front-matter. This is useful for linting, updating properties, etc. * Allow custom delimiters, when it's necessary for avoiding delimiter collision. -* Should return an object with at least these three properties (for debugging): +* Should return an object with at least these three properties: - `data`: the parsed YAML front matter, as a JSON object - `content`: the contents as a string, without the front matter - - `orig`: the "original" content + - `orig`: the "original" content (for debugging) @@ -85,7 +85,7 @@ Some libraries met most of the requirements, but _none met all of them_. Using Node's `require()` system: ```js -var matter = require('gray-matter'); +const matter = require('gray-matter'); ``` Or with [typescript](https://www.typescriptlang.org) @@ -126,6 +126,7 @@ gray-matter returns a `file` object with the following properties. - `file.data` **{Object}**: the object created by parsing front-matter - `file.content` **{String}**: the input string, with `matter` stripped - `file.excerpt` **{String}**: an excerpt, if [defined on the options](#optionsexcerpt) +- `file.empty` **{String}**: when the front-matter is "empty" (either all whitespace, nothing at all, or just comments and no data), the original string is set on this property. See [#65](https://github.com/jonschlinkert/gray-matter/issues/65) for details regarding use case. **Non-enumerable** @@ -134,7 +135,7 @@ In addition, the following non-enumberable properties are added to the object to - `file.orig` **{Buffer}**: the original input string (or buffer) - `file.language` **{String}**: the front-matter language that was parsed. `yaml` is the default - `file.matter` **{String}**: the _raw_, un-parsed front-matter string -- `file.stringify` **{Function}**: [stringify](#stringify) the file by converting `file.data` to a string in the given language, wrapping it in delimiters and appending it to `file.content`. +- `file.stringify` **{Function}**: [stringify](#stringify) the file by converting `file.data` to a string in the given language, wrapping it in delimiters and prepending it to `file.content`. ## Run the examples @@ -157,6 +158,8 @@ Then run any of the [examples](./examples) to see how gray-matter works: $ node examples/ ``` +**Links to examples** + {%= examples() %} @@ -179,14 +182,8 @@ If set to `excerpt: true`, it will look for the frontmatter delimiter, `---` by **Example** ```js -var file = matter([ - '---', - 'foo: bar', - '---', - 'This is an excerpt.', - '---', - 'This is content' -].join('\n'), {excerpt: true}); +const str = '---\nfoo: bar\n---\nThis is an excerpt.\n---\nThis is content'; +const file = matter(str, { excerpt: true }); ``` Results in: @@ -209,7 +206,7 @@ function firstFourLines(file, options) { file.excerpt = file.content.split('\n').slice(0, 4).join(' '); } -var file = matter([ +const file = matter([ '---', 'foo: bar', '---', @@ -282,13 +279,13 @@ Engines may either be an object with `parse` and (optionally) `stringify` method **Examples** ```js -var toml = require('toml'); +const toml = require('toml'); /** * defined as a function */ -var file = matter(str, { +const file = matter(str, { engines: { toml: toml.parse.bind(toml), } @@ -298,7 +295,7 @@ var file = matter(str, { * Or as an object */ -var file = matter(str, { +const file = matter(str, { engines: { toml: { parse: toml.parse.bind(toml), diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ced795..eebdf42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,24 @@ # Release history -## Unreleased +## 4.0.0 - 2018-04-01 + +### Breaking changes + +- Now requires node v4 or higher. + ## 3.0.0 - 2017-06-30 + ### Breaking changes -* `toml`, `coffee` and `cson` are no longer supported by default. Please see [`options.engines`](README.md#optionsengines) and the [examples](./examples) to learn how to add engines. + +- `toml`, `coffee` and `cson` are no longer supported by default. Please see [`options.engines`](README.md#optionsengines) and the [examples](./examples) to learn how to add engines. ### Added -* Support for [excerpts](README.md#optionsexcerpt). -* The returned object now has non-enumerable `matter` and `stringify` properties. + +- Support for [excerpts](README.md#optionsexcerpt). +- The returned object now has non-enumerable `matter` and `stringify` properties. ### Changed -* Refactored engines (parsers), so that it's easier to add parsers and stringifiers. -* `options.parsers` was renamed to [`options.engines`](README.md#optionsengines) + +- Refactored engines (parsers), so that it's easier to add parsers and stringifiers. +- `options.parsers` was renamed to [`options.engines`](README.md#optionsengines) diff --git a/LICENSE b/LICENSE index 3f2eca1..d32ab44 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2017, Jon Schlinkert. +Copyright (c) 2014-2018, Jon Schlinkert. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 08b869d..b4c1ad5 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,9 @@ Please see the [changelog](CHANGELOG.md) to learn about breaking changes that we Add the HTML in the following example to `example.html`, then add the following code to `example.js` and run `$ node example` (without the `$`): ```js -var fs = require('fs'); -var matter = require('gray-matter'); -var str = fs.readFileSync('example.html', 'utf8'); +const fs = require('fs'); +const matter = require('gray-matter'); +const str = fs.readFileSync('example.html', 'utf8'); console.log(matter(str)); ``` @@ -85,10 +85,10 @@ Some libraries met most of the requirements, but _none met all of them_. * Have no problem with complex content, including **non-front-matter** fenced code blocks that contain examples of YAML front matter. Other parsers fail on this. * Support stringifying back to front-matter. This is useful for linting, updating properties, etc. * Allow custom delimiters, when it's necessary for avoiding delimiter collision. -* Should return an object with at least these three properties (for debugging): +* Should return an object with at least these three properties: - `data`: the parsed YAML front matter, as a JSON object - `content`: the contents as a string, without the front matter - - `orig`: the "original" content + - `orig`: the "original" content (for debugging) @@ -97,7 +97,7 @@ Some libraries met most of the requirements, but _none met all of them_. Using Node's `require()` system: ```js -var matter = require('gray-matter'); +const matter = require('gray-matter'); ``` Or with [typescript](https://www.typescriptlang.org) @@ -138,6 +138,7 @@ gray-matter returns a `file` object with the following properties. * `file.data` **{Object}**: the object created by parsing front-matter * `file.content` **{String}**: the input string, with `matter` stripped * `file.excerpt` **{String}**: an excerpt, if [defined on the options](#optionsexcerpt) +* `file.empty` **{String}**: when the front-matter is "empty" (either all whitespace, nothing at all, or just comments and no data), the original string is set on this property. See [#65](https://github.com/jonschlinkert/gray-matter/issues/65) for details regarding use case. **Non-enumerable** @@ -146,7 +147,7 @@ In addition, the following non-enumberable properties are added to the object to * `file.orig` **{Buffer}**: the original input string (or buffer) * `file.language` **{String}**: the front-matter language that was parsed. `yaml` is the default * `file.matter` **{String}**: the _raw_, un-parsed front-matter string -* `file.stringify` **{Function}**: [stringify](#stringify) the file by converting `file.data` to a string in the given language, wrapping it in delimiters and appending it to `file.content`. +* `file.stringify` **{Function}**: [stringify](#stringify) the file by converting `file.data` to a string in the given language, wrapping it in delimiters and prepending it to `file.content`. ## Run the examples @@ -168,7 +169,8 @@ Then run any of the [examples](./examples) to see how gray-matter works: $ node examples/ ``` -* [cache](examples/cache.js) +**Links to examples** + * [coffee](examples/coffee.js) * [excerpt-separator](examples/excerpt-separator.js) * [excerpt-stringify](examples/excerpt-stringify.js) @@ -176,13 +178,16 @@ $ node examples/ * [javascript](examples/javascript.js) * [json-stringify](examples/json-stringify.js) * [json](examples/json.js) +* [restore-empty](examples/restore-empty.js) +* [sections-excerpt](examples/sections-excerpt.js) +* [sections](examples/sections.js) * [toml](examples/toml.js) * [yaml-stringify](examples/yaml-stringify.js) * [yaml](examples/yaml.js) ## API -### [matter](index.js#L30) +### [matter](index.js#L29) 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). @@ -195,12 +200,12 @@ Takes a string or object with `content` property, extracts and parses front-matt **Example** ```js -var matter = require('gray-matter'); +const matter = require('gray-matter'); console.log(matter('---\ntitle: Home\n---\nOther stuff')); //=> { data: { title: 'Home'}, content: 'Other stuff' } ``` -### [.stringify](index.js#L140) +### [.stringify](index.js#L160) 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. @@ -222,7 +227,7 @@ console.log(matter.stringify('foo bar baz', {title: 'Home'})); // foo bar baz ``` -### [.read](index.js#L160) +### [.read](index.js#L178) Synchronously read a file from the file system and parse front matter. Returns the same object as the [main function](#matter). @@ -235,10 +240,10 @@ Synchronously read a file from the file system and parse front matter. Returns t **Example** ```js -var file = matter.read('./content/blog-post.md'); +const file = matter.read('./content/blog-post.md'); ``` -### [.test](index.js#L175) +### [.test](index.js#L193) Returns true if the given `string` has front matter. @@ -263,14 +268,8 @@ If set to `excerpt: true`, it will look for the frontmatter delimiter, `---` by **Example** ```js -var file = matter([ - '---', - 'foo: bar', - '---', - 'This is an excerpt.', - '---', - 'This is content' -].join('\n'), {excerpt: true}); +const str = '---\nfoo: bar\n---\nThis is an excerpt.\n---\nThis is content'; +const file = matter(str, { excerpt: true }); ``` Results in: @@ -293,7 +292,7 @@ function firstFourLines(file, options) { file.excerpt = file.content.split('\n').slice(0, 4).join(' '); } -var file = matter([ +const file = matter([ '---', 'foo: bar', '---', @@ -365,13 +364,13 @@ Engines may either be an object with `parse` and (optionally) `stringify` method **Examples** ```js -var toml = require('toml'); +const toml = require('toml'); /** * defined as a function */ -var file = matter(str, { +const file = matter(str, { engines: { toml: toml.parse.bind(toml), } @@ -381,7 +380,7 @@ var file = matter(str, { * Or as an object */ -var file = matter(str, { +const file = matter(str, { engines: { toml: { parse: toml.parse.bind(toml), @@ -489,33 +488,26 @@ Decrecated, please use [options.engines](#optionsengines) instead. ## About -### Related projects +
+Contributing -* [assemble](https://www.npmjs.com/package/assemble): Get the rocks out of your socks! Assemble makes you fast at creating web projects… [more](https://github.com/assemble/assemble) | [homepage](https://github.com/assemble/assemble "Get the rocks out of your socks! Assemble makes you fast at creating web projects. Assemble is used by thousands of projects for rapid prototyping, creating themes, scaffolds, boilerplates, e-books, UI components, API documentation, blogs, building websit") -* [metalsmith](https://www.npmjs.com/package/metalsmith): An extremely simple, pluggable static site generator. | [homepage](https://github.com/segmentio/metalsmith#readme "An extremely simple, pluggable static site generator.") -* [verb](https://www.npmjs.com/package/verb): Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used… [more](https://github.com/verbose/verb) | [homepage](https://github.com/verbose/verb "Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used on hundreds of projects of all sizes to generate everything from API docs to readmes.") +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). -### Contributing +
-Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). +
+Running Tests -### Contributors +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` -| **Commits** | **Contributor** | -| --- | --- | -| 172 | [jonschlinkert](https://github.com/jonschlinkert) | -| 7 | [RobLoach](https://github.com/RobLoach) | -| 5 | [heymind](https://github.com/heymind) | -| 3 | [doowb](https://github.com/doowb) | -| 2 | [reccanti](https://github.com/reccanti) | -| 2 | [onokumus](https://github.com/onokumus) | -| 2 | [moozzyk](https://github.com/moozzyk) | -| 1 | [Ajedi32](https://github.com/Ajedi32) | -| 1 | [caesar](https://github.com/caesar) | -| 1 | [ianstormtaylor](https://github.com/ianstormtaylor) | -| 1 | [zachwhaley](https://github.com/zachwhaley) | - -### Building docs +
+ +
+Building docs _(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ @@ -525,20 +517,41 @@ To generate the readme, run the following command: $ npm install -g verbose/verb#dev verb-generate-readme && verb ``` -### Running tests +
-Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: +### Related projects -```sh -$ npm install && npm test -``` +You might also be interested in these projects: + +* [assemble](https://www.npmjs.com/package/assemble): Get the rocks out of your socks! Assemble makes you fast at creating web projects… [more](https://github.com/assemble/assemble) | [homepage](https://github.com/assemble/assemble "Get the rocks out of your socks! Assemble makes you fast at creating web projects. Assemble is used by thousands of projects for rapid prototyping, creating themes, scaffolds, boilerplates, e-books, UI components, API documentation, blogs, building websit") +* [metalsmith](https://www.npmjs.com/package/metalsmith): An extremely simple, pluggable static site generator. | [homepage](https://github.com/segmentio/metalsmith#readme "An extremely simple, pluggable static site generator.") +* [verb](https://www.npmjs.com/package/verb): Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used… [more](https://github.com/verbose/verb) | [homepage](https://github.com/verbose/verb "Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used on hundreds of projects of all sizes to generate everything from API docs to readmes.") + +### Contributors + +| **Commits** | **Contributor** | +| --- | --- | +| 174 | [jonschlinkert](https://github.com/jonschlinkert) | +| 7 | [RobLoach](https://github.com/RobLoach) | +| 5 | [heymind](https://github.com/heymind) | +| 4 | [doowb](https://github.com/doowb) | +| 3 | [aljopro](https://github.com/aljopro) | +| 2 | [reccanti](https://github.com/reccanti) | +| 2 | [onokumus](https://github.com/onokumus) | +| 2 | [moozzyk](https://github.com/moozzyk) | +| 1 | [Ajedi32](https://github.com/Ajedi32) | +| 1 | [caesar](https://github.com/caesar) | +| 1 | [ianstormtaylor](https://github.com/ianstormtaylor) | +| 1 | [qm3ster](https://github.com/qm3ster) | +| 1 | [zachwhaley](https://github.com/zachwhaley) | ### Author **Jon Schlinkert** -* [github/jonschlinkert](https://github.com/jonschlinkert) -* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) +* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert) +* [GitHub Profile](https://github.com/jonschlinkert) +* [Twitter Profile](https://twitter.com/jonschlinkert) ### License @@ -547,4 +560,4 @@ Released under the [MIT License](LICENSE). *** -_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on March 03, 2018._ \ No newline at end of file +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on April 01, 2018._ \ No newline at end of file diff --git a/bower.json b/bower.json index 6c0bea2..e72652a 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "gray-matter", "description": "Parse front-matter from a string or file. Fast, reliable and easy to use. Parses YAML front matter by default, but also has support for YAML, JSON, TOML or Coffee Front-Matter, with options to set custom delimiters. Used by metalsmith, assemble, verb and many other projects.", - "version": "3.0.5", + "version": "3.1.1", "homepage": "https://github.com/jonschlinkert/gray-matter", "authors": [ "Jon Schlinkert (https://github.com/jonschlinkert)" @@ -32,27 +32,25 @@ "index.js" ], "dependencies": { - "js-yaml": "^3.8.1", - "kind-of": "^5.0.0", + "define-property": "^2.0.2", + "js-yaml": "^3.11.0", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" }, "devDependencies": { - "ansi-bold": "^0.1.1", - "ansi-gray": "^0.1.1", - "ansi-magenta": "^0.1.1", - "benchmarked": "^0.2.5", - "coffee-script": "^1.12.6", + "ansi-green": "^0.1.1", + "benchmarked": "^2.0.0", + "coffeescript": "^2.2.3", "delimiter-regex": "^2.0.0", - "extend-shallow": "^2.0.1", - "for-own": "^0.1.4", - "front-matter": "^2.1.2", - "gulp-format-md": "^0.1.12", - "matched": "^1.0.2", + "extend-shallow": "^3.0.2", + "front-matter": "^2.3.0", + "gulp-format-md": "^1.0.0", "minimist": "^1.2.0", - "mocha": "^3.2.0", - "sort-object": "^3.0.2", - "toml": "^2.3.2", - "vinyl": "^2.0.2" + "mocha": "^3.5.3", + "toml": "^2.3.3", + "vinyl": "^2.1.0", + "write": "^1.0.3" }, "keywords": [ "assemble", @@ -106,5 +104,13 @@ } } }, - "types": "gray-matter.d.ts" + "types": "gray-matter.d.ts", + "browser": { + "fs": false + }, + "eslintConfig": { + "rules": { + "no-console": 0 + } + } } \ No newline at end of file diff --git a/examples/cache.js b/examples/cache.js deleted file mode 100644 index 931faa1..0000000 --- a/examples/cache.js +++ /dev/null @@ -1,20 +0,0 @@ -// https://github.com/jonschlinkert/gray-matter/issues/43 -var frontMatter = require('..'); - -var docs = [ - { - id: 1, - content: '' - }, - { - id: 2, - content: '' - } -]; - -var parsedDocs = docs.map(doc => { - var output = frontMatter(doc.content); - Object.assign(output, { id: doc.id }); - return output; -}).map(({ id }) => id); -console.log(parsedDocs); diff --git a/examples/coffee.js b/examples/coffee.js index e90aeff..0934114 100644 --- a/examples/coffee.js +++ b/examples/coffee.js @@ -1,10 +1,11 @@ -var path = require('path'); -var matter = require('..'); -var coffee = require('coffeescript'); -var magenta = require('ansi-magenta'); +const path = require('path'); +const matter = require('..'); +const coffee = require('coffeescript'); +const green = require('ansi-green'); +const fixture = path.join.bind(path, __dirname, 'fixtures'); +let file; -var fixture = path.join.bind(path, __dirname, 'fixtures'); -var engines = { +const engines = { coffee: { parse: function(str, options) { /* eslint no-eval: 0 */ @@ -13,13 +14,13 @@ var engines = { } }; -console.log(magenta('/* coffescript (detected after first delimiter) */')); -var file = matter.read(fixture('coffee-auto.md'), {engines: engines}); +console.log(green('/* coffescript (detected after first delimiter in front-matter) */')); +file = matter.read(fixture('coffee-auto.md'), {engines: engines}); console.log(file); console.log(); -console.log(magenta('/* coffescript (defined on options) */')); -var file = matter.read(fixture('coffee.md'), { +console.log(green('/* coffescript (defined on options) */')); +file = matter.read(fixture('coffee.md'), { language: 'coffee', engines: engines }); diff --git a/examples/excerpt-separator.js b/examples/excerpt-separator.js index 91006b3..f68d30f 100644 --- a/examples/excerpt-separator.js +++ b/examples/excerpt-separator.js @@ -1,10 +1,8 @@ -var path = require('path'); -var matter = require('..'); -var fixture = path.join.bind(path, __dirname, 'fixtures'); -var magenta = require('ansi-magenta'); +const matter = require('..'); +const green = require('ansi-green'); -console.log(magenta('/* excerpt with custom separator */')); -var file = matter([ +console.log(green('/* excerpt with custom separator */')); +const file = matter([ '---', 'foo: bar', '---', diff --git a/examples/excerpt-stringify.js b/examples/excerpt-stringify.js index e5cf294..c1c9e55 100644 --- a/examples/excerpt-stringify.js +++ b/examples/excerpt-stringify.js @@ -1,9 +1,7 @@ -var path = require('path'); -var matter = require('..'); -var fixture = path.join.bind(path, __dirname, 'fixtures'); -var magenta = require('ansi-magenta'); +const matter = require('..'); +const green = require('ansi-green'); -var file = matter([ +const file = matter([ '---', 'foo: bar', '---', @@ -12,9 +10,9 @@ var file = matter([ 'This is content' ].join('\n'), {excerpt_separator: ''}); -console.log(magenta('/* file object, with excerpt */')); +console.log(green('/* file object, with excerpt */')); console.log(file); console.log(); -console.log(magenta('/* stringified, with excerpt */')); +console.log(green('/* stringified, with excerpt */')); console.log(file.stringify()); diff --git a/examples/excerpt.js b/examples/excerpt.js index f263585..77320aa 100644 --- a/examples/excerpt.js +++ b/examples/excerpt.js @@ -1,10 +1,8 @@ -var path = require('path'); -var matter = require('..'); -var fixture = path.join.bind(path, __dirname, 'fixtures'); -var magenta = require('ansi-magenta'); +const matter = require('..'); +const green = require('ansi-green'); // excerpt as a boolean -var file1 = matter([ +const file1 = matter([ '---', 'foo: bar', '---', @@ -13,7 +11,7 @@ var file1 = matter([ 'This is content' ].join('\n'), {excerpt: true}); -console.log(magenta('/* excerpt: true */')); +console.log(green('/* excerpt: true */')); console.log(file1); // excerpt as a function @@ -23,16 +21,16 @@ function firstFourLines(file, options) { file.excerpt = file.content.split('\n').slice(0, 4).join(' '); } -var file2 = matter([ -'---', -'foo: bar', -'---', -'Only this', -'will be', -'in the', -'excerpt', -'but not this...' -].join('\n'), {excerpt: firstFourLines }); +const file2 = matter([ + '---', + 'foo: bar', + '---', + 'Only this', + 'will be', + 'in the', + 'excerpt', + 'but not this...' +].join('\n'), { excerpt: firstFourLines }); -console.log(magenta('/* excerpt: function(file, options) { ... } */')); -console.log(file2); \ No newline at end of file +console.log(green('/* excerpt: function(file, options) { ... } */')); +console.log(file2); diff --git a/examples/fixtures/sections-excerpt.md b/examples/fixtures/sections-excerpt.md new file mode 100644 index 0000000..9cfec28 --- /dev/null +++ b/examples/fixtures/sections-excerpt.md @@ -0,0 +1,32 @@ +---yaml +title: I'm front matter +--- + +This is an excerpt. +--- + +---aaa +title: First section +--- + +Section one. + +---bbb +title: Second section +--- + +Part 1. + +--- + +Part 2. + +--- + +Part 3. + +---ccc +title: Third section +--- + +Section three. diff --git a/examples/fixtures/sections.md b/examples/fixtures/sections.md new file mode 100644 index 0000000..361b6ec --- /dev/null +++ b/examples/fixtures/sections.md @@ -0,0 +1,31 @@ +---yaml +title: I'm front matter +--- + +This page has front matter that should be parsed before the sections. + +---aaa +title: First section +--- + +Section one. + +---bbb +title: Second section +--- + +Part 1. + +--- + +Part 2. + +--- + +Part 3. + +---ccc +title: Third section +--- + +Section three. diff --git a/examples/helper.js b/examples/helper.js index ab1fd3d..b4ea5eb 100644 --- a/examples/helper.js +++ b/examples/helper.js @@ -3,16 +3,16 @@ * the list of links to examples in the readme. */ -var fs = require('fs'); -var path = require('path'); +const fs = require('fs'); +const path = require('path'); module.exports = function() { - var files = fs.readdirSync(__dirname); - var links = []; - for (var i = 0; i < files.length; i++) { - var name = files[i]; - var ext = path.extname(name); - var stem = path.basename(name, ext); + const files = fs.readdirSync(__dirname); + const links = []; + for (let i = 0; i < files.length; i++) { + const name = files[i]; + const ext = path.extname(name); + const stem = path.basename(name, ext); if (stem !== 'helper' && ext === '.js') { links.push('- [' + stem + '](examples/' + name + ')'); } diff --git a/examples/javascript.js b/examples/javascript.js index 789244e..ae25c5d 100644 --- a/examples/javascript.js +++ b/examples/javascript.js @@ -1,8 +1,7 @@ -var path = require('path'); -var matter = require('..'); -var magenta = require('ansi-magenta'); +const matter = require('..'); +const green = require('ansi-green'); -var file = matter([ +const file = matter([ '---js', '{', ' reverse: function(str) {', @@ -13,10 +12,10 @@ var file = matter([ 'This is content' ].join('\n')); -console.log(magenta('/* javascript front-matter */')); +console.log(green('/* javascript front-matter */')); console.log(file); console.log(); -console.log(magenta('/* example after calling a function from front-matter */')); +console.log(green('/* example after calling a function from front-matter */')); file.data.baz = file.data.reverse('x,y,z'); console.log(file); diff --git a/examples/json-stringify.js b/examples/json-stringify.js index f0c29fb..2675aa1 100644 --- a/examples/json-stringify.js +++ b/examples/json-stringify.js @@ -1,9 +1,7 @@ -var path = require('path'); -var matter = require('..'); -var magenta = require('ansi-magenta'); -var fixture = path.join.bind(path, __dirname, 'fixtures'); +const matter = require('..'); +const green = require('ansi-green'); -var file = matter([ +const file1 = matter([ '---json', '{', ' "name": "gray-matter"', @@ -12,15 +10,15 @@ var file = matter([ 'This is content' ].join('\n')); -console.log(magenta('/* stringified to YAML, from JSON front-matter */')); -console.log(file.stringify({}, {language: 'yaml'})); +console.log(green('/* stringified to YAML, from JSON front-matter */')); +console.log(file1.stringify({}, {language: 'yaml'})); -var file = matter([ +const file2 = matter([ '---', 'title: Home', '---', 'This is content' ].join('\n')); -console.log(magenta('/* stringified JSON, from YAML front-matter */')); -console.log(file.stringify({}, {language: 'json', spaces: 2})); +console.log(green('/* stringified JSON, from YAML front-matter */')); +console.log(file2.stringify({}, {language: 'json', spaces: 2})); diff --git a/examples/json.js b/examples/json.js index 2e54be9..468669a 100644 --- a/examples/json.js +++ b/examples/json.js @@ -1,8 +1,6 @@ -var path = require('path'); -var matter = require('..'); -var magenta = require('ansi-magenta'); +const matter = require('..'); -var file = matter([ +const file1 = matter([ '---json', '{', ' "name": "gray-matter"', @@ -10,9 +8,9 @@ var file = matter([ '---', 'This is content' ].join('\n')); -console.log(file); +console.log(file1); -var file = matter([ +const file2 = matter([ '---json', '{', ' "name": "gray-matter"', @@ -20,4 +18,4 @@ var file = matter([ '---', 'This is content' ].join('\n')); -console.log(file); +console.log(file2); diff --git a/examples/restore-empty.js b/examples/restore-empty.js new file mode 100644 index 0000000..d0187cc --- /dev/null +++ b/examples/restore-empty.js @@ -0,0 +1,16 @@ +const matter = require('..'); + +/** + * Parse YAML front-matter + */ + +const str = `--- +--- +This is content`; +const file = matter(str); + +console.log(file); +if (file.isEmpty) { + file.content = str; +} +console.log(file); diff --git a/examples/sections-excerpt.js b/examples/sections-excerpt.js new file mode 100644 index 0000000..c870234 --- /dev/null +++ b/examples/sections-excerpt.js @@ -0,0 +1,9 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const matter = require('..'); +const str = fs.readFileSync(path.join(__dirname, 'fixtures', 'sections-excerpt.md')); + +const res = matter(str, { excerpt: true, sections: true }); +console.log(JSON.stringify(res, null, 2)); diff --git a/examples/sections.js b/examples/sections.js new file mode 100644 index 0000000..bc6a6f3 --- /dev/null +++ b/examples/sections.js @@ -0,0 +1,18 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const yaml = require('js-yaml'); +const matter = require('..'); +const str = fs.readFileSync(path.join(__dirname, 'fixtures', 'sections.md')); + +const file = matter(str, { + section: function(section, file) { + if (typeof section.data === 'string' && section.data.trim() !== '') { + section.data = yaml.safeLoad(section.data); + } + section.content = section.content.trim() + '\n'; + } +}); + +console.log(JSON.stringify(file, null, 2)); diff --git a/examples/toml.js b/examples/toml.js index 55eaac8..3be613c 100644 --- a/examples/toml.js +++ b/examples/toml.js @@ -1,21 +1,20 @@ -var path = require('path'); -var matter = require('..'); -var toml = require('toml'); -var magenta = require('ansi-magenta'); -var fixture = path.join.bind(path, __dirname, 'fixtures'); +const matter = require('..'); +const toml = require('toml'); /** * Parse TOML front-matter */ -var file = matter([ +const str = [ '---toml', 'title = "TOML"', 'description = "Front matter"', 'categories = "front matter toml"', '---', 'This is content' -].join('\n'), { +].join('\n'); + +const file = matter(str, { engines: { toml: toml.parse.bind(toml) } diff --git a/examples/yaml-stringify.js b/examples/yaml-stringify.js index 7d6bf86..508ed06 100644 --- a/examples/yaml-stringify.js +++ b/examples/yaml-stringify.js @@ -1,25 +1,22 @@ -var path = require('path'); -var matter = require('..'); -var magenta = require('ansi-magenta'); -var fixture = path.join.bind(path, __dirname, 'fixtures'); +const matter = require('..'); /** * Stringify back to YAML */ -var file = matter([ +const file = matter([ '---', 'foo: bar', '---', 'This is content' ].join('\n')); -var str = file.stringify(); -console.log(str); +const str1 = file.stringify(); +console.log(str1); /** * custom data */ -var str = file.stringify({baz: ['one', 'two', 'three']}); -console.log(str); +const str2 = file.stringify({baz: ['one', 'two', 'three']}); +console.log(str2); diff --git a/examples/yaml.js b/examples/yaml.js index 99ef601..cce4020 100644 --- a/examples/yaml.js +++ b/examples/yaml.js @@ -1,13 +1,10 @@ -var path = require('path'); -var matter = require('..'); -var magenta = require('ansi-magenta'); -var fixture = path.join.bind(path, __dirname, 'fixtures'); +const matter = require('..'); /** * Parse YAML front-matter */ -var file = matter([ +const file = matter([ '---', 'foo: bar', '---', diff --git a/index.js b/index.js index c5330b4..460f2ce 100644 --- a/index.js +++ b/index.js @@ -1,15 +1,14 @@ 'use strict'; -var fs = require('fs'); -var extend = require('extend-shallow'); -var parse = require('./lib/parse'); -var defaults = require('./lib/defaults'); -var stringify = require('./lib/stringify'); -var excerpt = require('./lib/excerpt'); -var engines = require('./lib/engines'); -var toFile = require('./lib/to-file'); -var utils = require('./lib/utils'); -var cache = {}; +const fs = require('fs'); +const sections = require('section-matter'); +const defaults = require('./lib/defaults'); +const stringify = require('./lib/stringify'); +const excerpt = require('./lib/excerpt'); +const engines = require('./lib/engines'); +const toFile = require('./lib/to-file'); +const parse = require('./lib/parse'); +const utils = require('./lib/utils'); /** * Takes a string or object with `content` property, extracts @@ -17,7 +16,7 @@ var cache = {}; * with `data`, `content` and other [useful properties](#returned-object). * * ```js - * var matter = require('gray-matter'); + * const matter = require('gray-matter'); * console.log(matter('---\ntitle: Home\n---\nOther stuff')); * //=> { data: { title: 'Home'}, content: 'Other stuff' } * ``` @@ -28,36 +27,45 @@ var cache = {}; */ function matter(input, options) { - var file = {data: {}, content: input, excerpt: '', orig: input}; - if (input === '') return file; + if (input === '') { + return { data: {}, content: input, excerpt: '', orig: input }; + } - file = toFile(input); - var cached = cache[file.content]; + let file = toFile(input); + const cached = matter.cache[file.content]; if (!options) { if (cached) { - file = extend({}, cached); + file = Object.assign({}, cached); file.orig = cached.orig; return file; } - cache[file.content] = 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) { - var opts = defaults(options); - var open = opts.delimiters[0]; - var close = '\n' + opts.delimiters[1]; - var str = file.content; + 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 - var openLen = open.length; + const openLen = open.length; if (!utils.startsWith(str, open, openLen)) { excerpt(file, opts); return file; @@ -72,17 +80,17 @@ function parseMatter(file, options) { // strip the opening delimiter str = str.slice(openLen); - var len = str.length; + const len = str.length; // use the language defined after first delimiter, if it exists - var language = matter.language(str, opts); + 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 - var closeIndex = str.indexOf(close); + let closeIndex = str.indexOf(close); if (closeIndex === -1) { closeIndex = len; } @@ -90,8 +98,16 @@ function parseMatter(file, options) { // get the raw front-matter block file.matter = str.slice(0, closeIndex); - // create file.data by parsing the raw file.matter block - file.data = parse(file.language, file.matter, opts); + 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) { @@ -107,6 +123,10 @@ function parseMatter(file, options) { } excerpt(file, opts); + + if (opts.sections === true || typeof opts.section === 'function') { + sections(file, opts.section); + } return file; } @@ -138,9 +158,7 @@ matter.engines = engines; */ matter.stringify = function(file, data, options) { - if (typeof file === 'string') { - file = matter(file, options); - } + if (typeof file === 'string') file = matter(file, options); return stringify(file, data, options); }; @@ -149,7 +167,7 @@ matter.stringify = function(file, data, options) { * front matter. Returns the same object as the [main function](#matter). * * ```js - * var file = matter.read('./content/blog-post.md'); + * 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. @@ -158,8 +176,8 @@ matter.stringify = function(file, data, options) { */ matter.read = function(filepath, options) { - var str = fs.readFileSync(filepath, 'utf8'); - var file = matter(str, options); + const str = fs.readFileSync(filepath, 'utf8'); + const file = matter(str, options); file.path = filepath; return file; }; @@ -173,8 +191,7 @@ matter.read = function(filepath, options) { */ matter.test = function(str, options) { - var opts = defaults(options); - return utils.startsWith(str, opts.delimiters[0]); + return utils.startsWith(str, defaults(options).delimiters[0]); }; /** @@ -186,14 +203,14 @@ matter.test = function(str, options) { */ matter.language = function(str, options) { - var opts = defaults(options); - var open = opts.delimiters[0]; + const opts = defaults(options); + const open = opts.delimiters[0]; if (matter.test(str)) { str = str.slice(open.length); } - var language = str.slice(0, str.search(/\r?\n/)); + const language = str.slice(0, str.search(/\r?\n/)); return { raw: language, name: language ? language.trim() : '' @@ -204,4 +221,6 @@ matter.language = function(str, options) { * Expose `matter` */ +matter.cache = {}; +matter.clearCache = () => (matter.cache = {}); module.exports = matter; diff --git a/lib/defaults.js b/lib/defaults.js index d61da1a..81d9e41 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -1,11 +1,10 @@ 'use strict'; -var extend = require('extend-shallow'); -var engines = require('./engines'); -var utils = require('./utils'); +const engines = require('./engines'); +const utils = require('./utils'); module.exports = function(options) { - var opts = extend({}, options); + const opts = Object.assign({}, options); // ensure that delimiters are an array opts.delimiters = utils.arrayify(opts.delims || opts.delimiters || '---'); @@ -14,6 +13,6 @@ module.exports = function(options) { } opts.language = (opts.language || opts.lang || 'yaml').toLowerCase(); - opts.engines = extend({}, engines, opts.parsers, opts.engines); + opts.engines = Object.assign({}, engines, opts.parsers, opts.engines); return opts; }; diff --git a/lib/engine.js b/lib/engine.js index 65cc0e0..d8f6c41 100644 --- a/lib/engine.js +++ b/lib/engine.js @@ -1,7 +1,7 @@ 'use strict'; module.exports = function(name, options) { - var engine = options.engines[name] || options.engines[aliase(name)]; + let engine = options.engines[name] || options.engines[aliase(name)]; if (typeof engine === 'undefined') { throw new Error('gray-matter engine "' + name + '" is not registered'); } diff --git a/lib/engines.js b/lib/engines.js index a299c08..38f993d 100644 --- a/lib/engines.js +++ b/lib/engines.js @@ -1,13 +1,12 @@ 'use strict'; -var extend = require('extend-shallow'); -var yaml = require('js-yaml'); +const yaml = require('js-yaml'); /** * Default engines */ -var engines = exports = module.exports; +const engines = exports = module.exports; /** * YAML @@ -25,7 +24,7 @@ engines.yaml = { engines.json = { parse: JSON.parse.bind(JSON), stringify: function(obj, options) { - var opts = extend({replacer: null, space: 2}, options); + const opts = Object.assign({replacer: null, space: 2}, options); return JSON.stringify(obj, opts.replacer, opts.space); } }; diff --git a/lib/excerpt.js b/lib/excerpt.js index 16a0aac..14d9904 100644 --- a/lib/excerpt.js +++ b/lib/excerpt.js @@ -1,9 +1,9 @@ 'use strict'; -var defaults = require('./defaults'); +const defaults = require('./defaults'); module.exports = function(file, options) { - var opts = defaults(options); + const opts = defaults(options); if (file.data == null) { file.data = {}; @@ -13,18 +13,17 @@ module.exports = function(file, options) { return opts.excerpt(file, opts); } - var sep = file.data.excerpt_separator || opts.excerpt_separator; + const sep = file.data.excerpt_separator || opts.excerpt_separator; if (sep == null && (opts.excerpt === false || opts.excerpt == null)) { return file; } - var delimiter = sep || opts.delimiters[0]; - if (typeof opts.excerpt === 'string') { - delimiter = opts.excerpt; - } + const delimiter = typeof opts.excerpt === 'string' + ? opts.excerpt + : (sep || opts.delimiters[0]); // if enabled, get the excerpt defined after front-matter - var idx = file.content.indexOf(delimiter); + const idx = file.content.indexOf(delimiter); if (idx !== -1) { file.excerpt = file.content.slice(0, idx); } diff --git a/lib/parse.js b/lib/parse.js index c49e9c4..e10ea9b 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -1,11 +1,11 @@ 'use strict'; -var getEngine = require('./engine'); -var defaults = require('./defaults'); +const getEngine = require('./engine'); +const defaults = require('./defaults'); module.exports = function(language, str, options) { - var opts = defaults(options); - var engine = getEngine(language, opts); + const opts = defaults(options); + const engine = getEngine(language, opts); if (typeof engine.parse !== 'function') { throw new TypeError('expected "' + language + '.parse" to be a function'); } diff --git a/lib/stringify.js b/lib/stringify.js index 5d937d4..b4c70a4 100644 --- a/lib/stringify.js +++ b/lib/stringify.js @@ -1,9 +1,8 @@ 'use strict'; -var extend = require('extend-shallow'); -var typeOf = require('kind-of'); -var getEngine = require('./engine'); -var defaults = require('./defaults'); +const typeOf = require('kind-of'); +const getEngine = require('./engine'); +const defaults = require('./defaults'); module.exports = function(file, data, options) { if (data == null && options == null) { @@ -20,26 +19,24 @@ module.exports = function(file, data, options) { } } - var str = file.content; - var opts = defaults(options); + const str = file.content; + const opts = defaults(options); if (data == null) { - if (!opts.data) { - return file; - } + if (!opts.data) return file; data = opts.data; } - var language = file.language || opts.language; - var engine = getEngine(language, opts); + 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 = extend({}, file.data, data); - var open = opts.delimiters[0]; - var close = opts.delimiters[1]; - var matter = engine.stringify(data, options).trim(); - var buf = ''; + 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); diff --git a/lib/to-file.js b/lib/to-file.js index 8d9a763..1594372 100644 --- a/lib/to-file.js +++ b/lib/to-file.js @@ -1,8 +1,9 @@ 'use strict'; -var typeOf = require('kind-of'); -var stringify = require('./stringify'); -var utils = require('./utils'); +const typeOf = require('kind-of'); +const define = require('define-property'); +const stringify = require('./stringify'); +const utils = require('./utils'); /** * Normalize the given value to ensure an object is returned @@ -18,45 +19,26 @@ module.exports = function(file) { file.data = {}; } - if (file.content == null) { + // if file was passed as an object, ensure that + // "file.content" is set + if (file.contents && file.content == null) { file.content = file.contents; } - var orig = utils.toBuffer(file.content); - Object.defineProperty(file, 'orig', { - configurable: true, - enumerable: false, - writable: true, - value: orig - }); - - Object.defineProperty(file, 'matter', { - configurable: true, - enumerable: false, - writable: true, - value: file.matter || '' - }); - - Object.defineProperty(file, 'language', { - configurable: true, - enumerable: false, - writable: true, - value: file.language || '' - }); - - Object.defineProperty(file, 'stringify', { - configurable: true, - enumerable: false, - writable: true, - value: function(data, options) { - if (options && options.language) { - file.language = options.language; - } - return stringify(file, data, options); + // set non-enumerable properties on the file object + define(file, 'orig', utils.toBuffer(file.content)); + define(file, 'language', file.language || ''); + define(file, 'matter', file.matter || ''); + 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; }; diff --git a/lib/utils.js b/lib/utils.js index 4e8270d..eed30e7 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,33 +1,26 @@ 'use strict'; -var stripBom = require('strip-bom-string'); -exports.typeOf = require('kind-of'); +const stripBom = require('strip-bom-string'); +const typeOf = require('kind-of'); /** * Returns true if `val` is a buffer */ -exports.isBuffer = function(val) { - return exports.typeOf(val) === 'buffer'; -}; +exports.isBuffer = val => typeOf(val) === 'buffer'; /** * Returns true if `val` is an object */ -exports.isObject = function(val) { - return exports.typeOf(val) === 'object'; -}; +exports.isObject = val => typeOf(val) === 'object'; /** * Cast `input` to a buffer */ exports.toBuffer = function(input) { - if (typeof input === 'string') { - return new Buffer(input); - } - return input; + return typeof input === 'string' ? Buffer.from(input) : input; }; /** @@ -35,9 +28,7 @@ exports.toBuffer = function(input) { */ exports.toString = function(input) { - if (exports.isBuffer(input)) { - return stripBom(String(input)); - } + if (exports.isBuffer(input)) return stripBom(String(input)); if (typeof input !== 'string') { throw new TypeError('expected input to be a string or buffer'); } diff --git a/package.json b/package.json index 410c170..eff8eb6 100644 --- a/package.json +++ b/package.json @@ -28,26 +28,25 @@ ], "main": "index.js", "engines": { - "node": ">=0.10.0" + "node": ">=6.0" }, "scripts": { "test": "mocha" }, - "browser": { - "fs": false - }, "dependencies": { - "extend-shallow": "^2.0.1", - "js-yaml": "^3.10.0", - "kind-of": "^5.0.2", + "define-property": "^2.0.2", + "js-yaml": "^3.11.0", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" }, "devDependencies": { - "ansi-magenta": "^0.1.1", + "ansi-green": "^0.1.1", "benchmarked": "^2.0.0", - "coffeescript": "1.12.7", + "coffeescript": "^2.2.3", "delimiter-regex": "^2.0.0", - "front-matter": "^2.2.0", + "extend-shallow": "^3.0.2", + "front-matter": "^2.3.0", "gulp-format-md": "^1.0.0", "minimist": "^1.2.0", "mocha": "^3.5.3", @@ -87,7 +86,15 @@ "yaml", "yfm" ], + "browser": { + "fs": false + }, "typings": "gray-matter.d.ts", + "eslintConfig": { + "rules": { + "no-console": 0 + } + }, "verb": { "toc": false, "layout": "default", diff --git a/test/matter-empty.js b/test/matter-empty.js new file mode 100644 index 0000000..edc5b7e --- /dev/null +++ b/test/matter-empty.js @@ -0,0 +1,35 @@ +'use strict'; + +require('mocha'); +var assert = require('assert'); +var utils = require('../lib/utils'); +var matter = require('..'); + +describe('gray-matter', function() { + it('should work with empty front-matter', function() { + var file1 = matter('---\n---\nThis is content'); + assert.equal(file1.content, 'This is content'); + assert.deepEqual(file1.data, {}); + + var file2 = matter('---\n\n---\nThis is content'); + assert.equal(file2.content, 'This is content'); + assert.deepEqual(file2.data, {}); + + var file3 = matter('---\n\n\n\n\n\n---\nThis is content'); + assert.equal(file3.content, 'This is content'); + assert.deepEqual(file3.data, {}); + }); + + it('should add content with empty front matter to file.empty', function() { + assert.deepEqual(matter('---\n---').empty, '---\n---'); + }); + + it('should update file.isEmpty to true', function() { + assert.deepEqual(matter('---\n---').isEmpty, true); + }); + + it('should work when front-matter has comments', function() { + const fixture = '---\n # this is a comment\n# another one\n---'; + assert.deepEqual(matter(fixture).empty, fixture); + }); +}); diff --git a/test/matter.js b/test/matter.js index 2f86ff7..99d5b98 100644 --- a/test/matter.js +++ b/test/matter.js @@ -21,20 +21,6 @@ describe('gray-matter', function() { assert.equal(actual.orig.toString(), fixture); }); - it('should work with empty front-matter', function() { - var file1 = matter('---\n---\nThis is content'); - assert.equal(file1.content, 'This is content'); - assert.deepEqual(file1.data, {}); - - var file2 = matter('---\n\n---\nThis is content'); - assert.equal(file2.content, 'This is content'); - assert.deepEqual(file2.data, {}); - - var file3 = matter('---\n\n\n\n\n\n---\nThis is content'); - assert.equal(file3.content, 'This is content'); - assert.deepEqual(file3.data, {}); - }); - it('should throw parsing errors', function() { assert.throws(function() { matter('---whatever\nabc: xyz\n---'); From cd98d0f9a2d4bda494430ed3ed908ac6bedc4d5c Mon Sep 17 00:00:00 2001 From: jonschlinkert Date: Sun, 1 Apr 2018 23:33:48 -0400 Subject: [PATCH 11/23] remove dep --- lib/to-file.js | 9 ++++----- lib/utils.js | 9 +++++++++ package.json | 1 - 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/to-file.js b/lib/to-file.js index 1594372..799bb5d 100644 --- a/lib/to-file.js +++ b/lib/to-file.js @@ -1,7 +1,6 @@ 'use strict'; const typeOf = require('kind-of'); -const define = require('define-property'); const stringify = require('./stringify'); const utils = require('./utils'); @@ -26,10 +25,10 @@ module.exports = function(file) { } // set non-enumerable properties on the file object - define(file, 'orig', utils.toBuffer(file.content)); - define(file, 'language', file.language || ''); - define(file, 'matter', file.matter || ''); - define(file, 'stringify', function(data, options) { + utils.define(file, 'orig', utils.toBuffer(file.content)); + 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; } diff --git a/lib/utils.js b/lib/utils.js index eed30e7..91428ca 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -3,6 +3,15 @@ const stripBom = require('strip-bom-string'); const typeOf = require('kind-of'); +exports.define = function(obj, key, val) { + Reflect.defineProperty(obj, key, { + enumerable: false, + configurable: true, + writable: true, + value: val + }); +}; + /** * Returns true if `val` is a buffer */ diff --git a/package.json b/package.json index eff8eb6..29cf02f 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "test": "mocha" }, "dependencies": { - "define-property": "^2.0.2", "js-yaml": "^3.11.0", "kind-of": "^6.0.2", "section-matter": "^1.0.0", From 280c4b43fc0166362131e9864d5d52243d10178d Mon Sep 17 00:00:00 2001 From: jonschlinkert Date: Sun, 1 Apr 2018 23:34:56 -0400 Subject: [PATCH 12/23] 4.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 29cf02f..c473abc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "gray-matter", "description": "Parse front-matter from a string or file. Fast, reliable and easy to use. Parses YAML front matter by default, but also has support for YAML, JSON, TOML or Coffee Front-Matter, with options to set custom delimiters. Used by metalsmith, assemble, verb and many other projects.", - "version": "3.1.1", + "version": "4.0.0", "homepage": "https://github.com/jonschlinkert/gray-matter", "author": "Jon Schlinkert (https://github.com/jonschlinkert)", "contributors": [ From c6735b84e7abb0521622ca2c8df76892195d1549 Mon Sep 17 00:00:00 2001 From: jonschlinkert Date: Sun, 1 Apr 2018 23:40:23 -0400 Subject: [PATCH 13/23] 4.0.1 Add `.isEmpty` to readme. (oops I thought I added this already!) --- .verb.md | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/.verb.md b/.verb.md index 05a92b5..ecda709 100644 --- a/.verb.md +++ b/.verb.md @@ -127,6 +127,7 @@ gray-matter returns a `file` object with the following properties. - `file.content` **{String}**: the input string, with `matter` stripped - `file.excerpt` **{String}**: an excerpt, if [defined on the options](#optionsexcerpt) - `file.empty` **{String}**: when the front-matter is "empty" (either all whitespace, nothing at all, or just comments and no data), the original string is set on this property. See [#65](https://github.com/jonschlinkert/gray-matter/issues/65) for details regarding use case. +- `file.isEmpty` **{Boolean}**: true if front-matter is empty. **Non-enumerable** diff --git a/README.md b/README.md index b4c1ad5..4f3ca6e 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,7 @@ gray-matter returns a `file` object with the following properties. * `file.content` **{String}**: the input string, with `matter` stripped * `file.excerpt` **{String}**: an excerpt, if [defined on the options](#optionsexcerpt) * `file.empty` **{String}**: when the front-matter is "empty" (either all whitespace, nothing at all, or just comments and no data), the original string is set on this property. See [#65](https://github.com/jonschlinkert/gray-matter/issues/65) for details regarding use case. +* `file.isEmpty` **{Boolean}**: true if front-matter is empty. **Non-enumerable** From 1d02a88555253e32886b52b16440b371f61dad4c Mon Sep 17 00:00:00 2001 From: jonschlinkert Date: Sun, 1 Apr 2018 23:40:30 -0400 Subject: [PATCH 14/23] 4.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c473abc..3ec31de 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "gray-matter", "description": "Parse front-matter from a string or file. Fast, reliable and easy to use. Parses YAML front matter by default, but also has support for YAML, JSON, TOML or Coffee Front-Matter, with options to set custom delimiters. Used by metalsmith, assemble, verb and many other projects.", - "version": "4.0.0", + "version": "4.0.1", "homepage": "https://github.com/jonschlinkert/gray-matter", "author": "Jon Schlinkert (https://github.com/jonschlinkert)", "contributors": [ From 73fa659e9757edc36b23db005e5ed2c1783e3590 Mon Sep 17 00:00:00 2001 From: Arlair Date: Wed, 18 Apr 2018 19:22:29 +0700 Subject: [PATCH 15/23] GrayMatterFile interface typo: excrept `GrayMatterFile` interface property `excrept` should be `excerpt`? --- gray-matter.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gray-matter.d.ts b/gray-matter.d.ts index a9fc520..6cf0c42 100644 --- a/gray-matter.d.ts +++ b/gray-matter.d.ts @@ -39,7 +39,7 @@ declare namespace matter { interface GrayMatterFile { data: object content: string - excrept?: string + excerpt?: string orig: Buffer | I language: string matter: string From 7b751e0b71c32ca47faf3f4d27ebae555d4c8a7f Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Thu, 26 Apr 2018 17:16:52 +0200 Subject: [PATCH 16/23] use index type for GrayMatterFile.data --- gray-matter.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gray-matter.d.ts b/gray-matter.d.ts index 6cf0c42..d12b972 100644 --- a/gray-matter.d.ts +++ b/gray-matter.d.ts @@ -37,7 +37,7 @@ declare namespace matter { delimiters?: string | [string, string] } interface GrayMatterFile { - data: object + data: { [key: string]: any } content: string excerpt?: string orig: Buffer | I From d9255dc66d9d11e71a2b961883c8fbd6bd25fe95 Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Thu, 26 Apr 2018 17:29:51 +0200 Subject: [PATCH 17/23] fix GrayMatterOption.engines type --- gray-matter.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gray-matter.d.ts b/gray-matter.d.ts index 6cf0c42..9f3f7a6 100644 --- a/gray-matter.d.ts +++ b/gray-matter.d.ts @@ -30,8 +30,8 @@ declare namespace matter { excerpt_separator?: string engines?: { [index: string]: - | ((string) => object) - | { parse: (string) => object; stringify?: (object) => string } + | ((input: string) => object) + | { parse: (input: string) => object; stringify?: (data: object) => string } } language?: string delimiters?: string | [string, string] From 86be0eb55dc5d601e5ca5e56881c46fb89e1e0c8 Mon Sep 17 00:00:00 2001 From: Ajay Narain Mathur Date: Sat, 14 Jul 2018 14:32:50 +1000 Subject: [PATCH 18/23] Arrow function breaks in IE 11 `=>` is not supported in IE11, thus breaks the website in IE11 when it uses gray-matter library. --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 460f2ce..90a6647 100644 --- a/index.js +++ b/index.js @@ -222,5 +222,5 @@ matter.language = function(str, options) { */ matter.cache = {}; -matter.clearCache = () => (matter.cache = {}); +matter.clearCache = function() { matter.cache = {} }; module.exports = matter; From 82b8e821b36d5238b798ee08738cf20b04e64110 Mon Sep 17 00:00:00 2001 From: Ajay Narain Mathur Date: Mon, 26 Nov 2018 16:23:38 +1100 Subject: [PATCH 19/23] added gray matter loader to related project --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4f3ca6e..d5d1e0a 100644 --- a/README.md +++ b/README.md @@ -527,6 +527,7 @@ You might also be interested in these projects: * [assemble](https://www.npmjs.com/package/assemble): Get the rocks out of your socks! Assemble makes you fast at creating web projects… [more](https://github.com/assemble/assemble) | [homepage](https://github.com/assemble/assemble "Get the rocks out of your socks! Assemble makes you fast at creating web projects. Assemble is used by thousands of projects for rapid prototyping, creating themes, scaffolds, boilerplates, e-books, UI components, API documentation, blogs, building websit") * [metalsmith](https://www.npmjs.com/package/metalsmith): An extremely simple, pluggable static site generator. | [homepage](https://github.com/segmentio/metalsmith#readme "An extremely simple, pluggable static site generator.") * [verb](https://www.npmjs.com/package/verb): Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used… [more](https://github.com/verbose/verb) | [homepage](https://github.com/verbose/verb "Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used on hundreds of projects of all sizes to generate everything from API docs to readmes.") +* [gray-matter-loader](https://github.com/atlassian/gray-matter-loader): A webpack loader for gray-matter. [homepage](https://github.com/atlassian/gray-matter-loader#gray-matter-loader) ### Contributors From eee3c0b6c1c3aa4dc38a4ad0217e91c2bee69680 Mon Sep 17 00:00:00 2001 From: Robert Massaioli Date: Fri, 11 Jan 2019 09:26:54 +1100 Subject: [PATCH 20/23] Adding in more test cases for invalid data. --- test/matter.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/matter.js b/test/matter.js index 99d5b98..9e40393 100644 --- a/test/matter.js +++ b/test/matter.js @@ -21,12 +21,27 @@ describe('gray-matter', function() { assert.equal(actual.orig.toString(), fixture); }); - it('should throw parsing errors', function() { + it('extra characters should throw parsing errors', function() { assert.throws(function() { matter('---whatever\nabc: xyz\n---'); }); }); + it('boolean yaml types should still return the empty object', function() { + var actual = matter('--- true\n---'); + assert.deepEqual(actual.data, {}); + }); + + it('string yaml types should still return the empty object', function() { + var actual = matter('--- true\n---'); + assert.deepEqual(actual.data, {}); + }); + + it('number yaml types should still return the empty object', function() { + var actual = matter('--- 42\n---'); + assert.deepEqual(actual.data, {}); + }); + it('should throw an error when a string is not passed:', function() { assert.throws(function() { matter(); From a425516286699f935183d461e2ce5473b5fe1d25 Mon Sep 17 00:00:00 2001 From: Robert Massaioli Date: Fri, 11 Jan 2019 09:31:11 +1100 Subject: [PATCH 21/23] Removing all references to arrow functions. --- lib/utils.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 91428ca..96e7ce0 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -16,13 +16,17 @@ exports.define = function(obj, key, val) { * Returns true if `val` is a buffer */ -exports.isBuffer = val => typeOf(val) === 'buffer'; +exports.isBuffer = function(val) { + return typeOf(val) === 'buffer'; +}; /** * Returns true if `val` is an object */ -exports.isObject = val => typeOf(val) === 'object'; +exports.isObject = function(val) { + return typeOf(val) === 'object'; +}; /** * Cast `input` to a buffer From 7e3edf3d886e0797a61ba9559276f8c2ec287b4f Mon Sep 17 00:00:00 2001 From: Robert Massaioli Date: Fri, 11 Jan 2019 09:32:22 +1100 Subject: [PATCH 22/23] Putting in better formatting for the clearCache function. --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 90a6647..7d49331 100644 --- a/index.js +++ b/index.js @@ -222,5 +222,7 @@ matter.language = function(str, options) { */ matter.cache = {}; -matter.clearCache = function() { matter.cache = {} }; +matter.clearCache = function() { + matter.cache = {}; +}; module.exports = matter; From 90f81203005a26893247c03eb4790c5e082cb319 Mon Sep 17 00:00:00 2001 From: Robert Massaioli Date: Fri, 11 Jan 2019 13:43:52 +1100 Subject: [PATCH 23/23] 4.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ec31de..bdce8c9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "gray-matter", "description": "Parse front-matter from a string or file. Fast, reliable and easy to use. Parses YAML front matter by default, but also has support for YAML, JSON, TOML or Coffee Front-Matter, with options to set custom delimiters. Used by metalsmith, assemble, verb and many other projects.", - "version": "4.0.1", + "version": "4.0.2", "homepage": "https://github.com/jonschlinkert/gray-matter", "author": "Jon Schlinkert (https://github.com/jonschlinkert)", "contributors": [