Complete TOML and JSON front matter (#1402)

* Complete TOML and JSON front matter

* Add frontmatter settings
This commit is contained in:
Felix Häusler 2019-10-02 23:27:29 +02:00 committed by GitHub
parent 60a12ae221
commit ddf9c50a42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 123 additions and 11 deletions

View File

@ -44,6 +44,8 @@ Preferences can be controlled and modified in the settings window or via the `pr
| preferHeadingStyle | String | `atx` | The preferred heading style in Mark Text, optional value `atx` `setext`, [more info](https://spec.commonmark.org/0.29/#atx-headings) | | preferHeadingStyle | String | `atx` | The preferred heading style in Mark Text, optional value `atx` `setext`, [more info](https://spec.commonmark.org/0.29/#atx-headings) |
| tabSize | Number | 4 | The number of spaces a tab is equal to | | tabSize | Number | 4 | The number of spaces a tab is equal to |
| listIndentation | String | 1 | The list indentation of sub list items or paragraphs, optional value `dfm`, `tab` or number 1~4 | | listIndentation | String | 1 | The list indentation of sub list items or paragraphs, optional value `dfm`, `tab` or number 1~4 |
| frontmatterType | String | `-` | The frontmatter type: `-` (YAML), `+` (TOML), `;` (JSON) or `{` (JSON) |
#### View #### View

View File

@ -165,6 +165,15 @@
4 4
] ]
}, },
"frontmatterType": {
"description": "Markdown--The frontmatter type",
"enum": [
"-",
"+",
";",
"{"
]
},
"theme": { "theme": {
"description": "Theme--Select the theme used in Mark Text", "description": "Theme--Select the theme used in Mark Text",
"type": "string" "type": "string"

View File

@ -250,6 +250,7 @@ export const MUYA_DEFAULT_OPTION = {
tabSize: 4, tabSize: 4,
// bullet/list marker width + listIndentation, tab or Daring Fireball Markdown (4 spaces) --> list indentation // bullet/list marker width + listIndentation, tab or Daring Fireball Markdown (4 spaces) --> list indentation
listIndentation: 1, listIndentation: 1,
frontmatterType: '-',
sequenceTheme: 'hand', // hand or simple sequenceTheme: 'hand', // hand or simple
mermaidTheme: 'default', // dark / forest / default mermaidTheme: 'default', // dark / forest / default
vegaTheme: 'latimes', // excel / ggplot2 / quartz / vox / fivethirtyeight / dark / latimes vegaTheme: 'latimes', // excel / ggplot2 / quartz / vox / fivethirtyeight / dark / latimes

View File

@ -68,10 +68,33 @@ const paragraphCtrl = ContentState => {
ContentState.prototype.handleFrontMatter = function () { ContentState.prototype.handleFrontMatter = function () {
const firstBlock = this.blocks[0] const firstBlock = this.blocks[0]
if (firstBlock.type === 'pre' && firstBlock.functionType === 'frontmatter') return if (firstBlock.type === 'pre' && firstBlock.functionType === 'frontmatter') return
const lang = 'yaml'
const { frontmatterType } = this.muya.options
let lang
let style
switch (frontmatterType) {
case '+':
lang = 'toml'
style = '+'
break
case ';':
lang = 'json'
style = ';'
break
case '{':
lang = 'json'
style = '{'
break
default:
lang = 'yaml'
style = '-'
break
}
const frontMatter = this.createBlock('pre', { const frontMatter = this.createBlock('pre', {
functionType: 'frontmatter', functionType: 'frontmatter',
lang lang,
style
}) })
const codeBlock = this.createBlock('code', { const codeBlock = this.createBlock('code', {
lang lang
@ -626,6 +649,7 @@ const paragraphCtrl = ContentState => {
} else { } else {
anchor = this.getAnchor(block) anchor = this.getAnchor(block)
} }
// You can not insert paragraph before frontmatter // You can not insert paragraph before frontmatter
if (!anchor || anchor && anchor.functionType === 'frontmatter' && location === 'before') { if (!anchor || anchor && anchor.functionType === 'frontmatter' && location === 'before') {
return return

View File

@ -34,7 +34,7 @@ export const block = {
text: /^[^\n]+/, text: /^[^\n]+/,
// extra // extra
frontmatter: /^---\n([\s\S]+?)---(?:\n+|$)/, frontmatter: /^(?:(?:---\n([\s\S]+?)---)|(?:\+\+\+\n([\s\S]+?)\+\+\+)|(?:;;;\n([\s\S]+?);;;)|(?:\{\n([\s\S]+?)\}))(?:\n{2,}|\n{1,2}$)/,
multiplemath: /^\$\$\n([\s\S]+?)\n\$\$(?:\n+|$)/ multiplemath: /^\$\$\n([\s\S]+?)\n\$\$(?:\n+|$)/
} }

View File

@ -51,14 +51,32 @@ Lexer.prototype.token = function (src, top) {
let checked let checked
// Only check front matter at the begining of a markdown file. // Only check front matter at the begining of a markdown file.
// Why "checkFrontmatter" and "top"? See note in "blockquote". // Please see note in "blockquote" why we need "checkFrontmatter" and "top".
if (frontMatter) { if (frontMatter) {
cap = this.rules.frontmatter.exec(src) cap = this.rules.frontmatter.exec(src)
if (this.checkFrontmatter && top && cap) { if (this.checkFrontmatter && top && cap) {
src = src.substring(cap[0].length) src = src.substring(cap[0].length)
let lang
let style
let text
if (cap[1]) {
lang = 'yaml'
style = '-'
text = cap[1]
} else if (cap[2]) {
lang = 'toml'
style = '+'
text = cap[2]
} else if (cap[3] || cap[4]) {
lang = 'json'
style = cap[3] ? ';' : '{'
text = cap[3] || cap[4]
}
this.tokens.push({ this.tokens.push({
type: 'frontmatter', type: 'frontmatter',
text: cap[1] text,
style,
lang
}) })
} }
this.checkFrontmatter = false this.checkFrontmatter = false

View File

@ -192,12 +192,34 @@ class ExportMarkdown {
} }
normalizeFrontMatter (block, indent) { // preBlock normalizeFrontMatter (block, indent) { // preBlock
let startToken
let endToken
switch (block.lang) {
case 'yaml':
startToken = '---\n'
endToken = '---\n'
break
case 'toml':
startToken = '+++\n'
endToken = '+++\n'
break
case 'json':
if (block.style === ';') {
startToken = ';;;\n'
endToken = ';;;\n'
} else {
startToken = '{\n'
endToken = '}\n'
}
break
}
const result = [] const result = []
result.push('---\n') result.push(startToken)
for (const line of block.children[0].children) { for (const line of block.children[0].children) {
result.push(`${line.text}\n`) result.push(`${line.text}\n`)
} }
result.push('---\n') result.push(endToken)
return result.join('') return result.join('')
} }

View File

@ -86,11 +86,12 @@ const importRegister = ContentState => {
while ((token = tokens.shift())) { while ((token = tokens.shift())) {
switch (token.type) { switch (token.type) {
case 'frontmatter': { case 'frontmatter': {
const lang = 'yaml' const { lang, style } = token
value = token.text value = token.text
block = this.createBlock('pre', { block = this.createBlock('pre', {
functionType: token.type, functionType: token.type,
lang lang,
style
}) })
const codeBlock = this.createBlock('code', { const codeBlock = this.createBlock('code', {
lang lang

View File

@ -133,6 +133,7 @@ export default {
orderListDelimiter: state => state.preferences.orderListDelimiter, orderListDelimiter: state => state.preferences.orderListDelimiter,
tabSize: state => state.preferences.tabSize, tabSize: state => state.preferences.tabSize,
listIndentation: state => state.preferences.listIndentation, listIndentation: state => state.preferences.listIndentation,
frontmatterType: state => state.preferences.frontmatterType,
lineHeight: state => state.preferences.lineHeight, lineHeight: state => state.preferences.lineHeight,
fontSize: state => state.preferences.fontSize, fontSize: state => state.preferences.fontSize,
codeFontSize: state => state.preferences.codeFontSize, codeFontSize: state => state.preferences.codeFontSize,
@ -226,6 +227,12 @@ export default {
editor.setListIndentation(value) editor.setListIndentation(value)
} }
}, },
frontmatterType: function (value, oldValue) {
const { editor } = this
if (value !== oldValue && editor) {
editor.setOptions({ frontmatterType: value })
}
},
hideQuickInsertHint: function (value, oldValue) { hideQuickInsertHint: function (value, oldValue) {
const { editor } = this const { editor } = this
if (value !== oldValue && editor) { if (value !== oldValue && editor) {
@ -323,6 +330,7 @@ export default {
orderListDelimiter, orderListDelimiter,
tabSize, tabSize,
listIndentation, listIndentation,
frontmatterType,
hideQuickInsertHint, hideQuickInsertHint,
editorLineWidth, editorLineWidth,
theme theme
@ -358,12 +366,14 @@ export default {
orderListDelimiter, orderListDelimiter,
tabSize, tabSize,
listIndentation, listIndentation,
frontmatterType,
hideQuickInsertHint, hideQuickInsertHint,
imageAction: this.imageAction.bind(this), imageAction: this.imageAction.bind(this),
imagePathPicker: this.imagePathPicker.bind(this), imagePathPicker: this.imagePathPicker.bind(this),
clipboardFilePath: guessClipboardFilePath, clipboardFilePath: guessClipboardFilePath,
imagePathAutoComplete: this.imagePathAutoComplete.bind(this) imagePathAutoComplete: this.imagePathAutoComplete.bind(this)
} }
if (/dark/i.test(theme)) { if (/dark/i.test(theme)) {
Object.assign(options, { Object.assign(options, {
mermaidTheme: 'dark', mermaidTheme: 'dark',

View File

@ -58,3 +58,17 @@ export const listIndentationOptions = [{
label: '4 spaces', label: '4 spaces',
value: 4 value: 4
}] }]
export const frontmatterTypeOptions = [{
label: 'YAML',
value: '-'
}, {
label: 'TOML',
value: '+'
}, {
label: 'JSON (;;;)',
value: ';'
}, {
label: 'JSON ({})',
value: '{'
}]

View File

@ -40,6 +40,12 @@
:options="listIndentationOptions" :options="listIndentationOptions"
:onChange="value => onSelectChange('listIndentation', value)" :onChange="value => onSelectChange('listIndentation', value)"
></cus-select> ></cus-select>
<cus-select
description="The frontmatter type"
:value="frontmatterType"
:options="frontmatterTypeOptions"
:onChange="value => onSelectChange('frontmatterType', value)"
></cus-select>
</div> </div>
</template> </template>
@ -52,7 +58,8 @@ import {
orderListDelimiterOptions, orderListDelimiterOptions,
preferHeadingStyleOptions, preferHeadingStyleOptions,
tabSizeOptions, tabSizeOptions,
listIndentationOptions listIndentationOptions,
frontmatterTypeOptions
} from './config' } from './config'
export default { export default {
@ -66,6 +73,7 @@ export default {
this.preferHeadingStyleOptions = preferHeadingStyleOptions this.preferHeadingStyleOptions = preferHeadingStyleOptions
this.tabSizeOptions = tabSizeOptions this.tabSizeOptions = tabSizeOptions
this.listIndentationOptions = listIndentationOptions this.listIndentationOptions = listIndentationOptions
this.frontmatterTypeOptions = frontmatterTypeOptions
return {} return {}
}, },
computed: { computed: {
@ -75,7 +83,8 @@ export default {
orderListDelimiter: state => state.preferences.orderListDelimiter, orderListDelimiter: state => state.preferences.orderListDelimiter,
preferHeadingStyle: state => state.preferences.preferHeadingStyle, preferHeadingStyle: state => state.preferences.preferHeadingStyle,
tabSize: state => state.preferences.tabSize, tabSize: state => state.preferences.tabSize,
listIndentation: state => state.preferences.listIndentation listIndentation: state => state.preferences.listIndentation,
frontmatterType: state => state.preferences.frontmatterType
}) })
}, },
methods: { methods: {

View File

@ -35,6 +35,7 @@ const state = {
preferHeadingStyle: 'atx', preferHeadingStyle: 'atx',
tabSize: 4, tabSize: 4,
listIndentation: 1, listIndentation: 1,
frontmatterType: '-',
theme: 'light', theme: 'light',

View File

@ -32,6 +32,7 @@
"preferHeadingStyle": "atx", "preferHeadingStyle": "atx",
"tabSize": 4, "tabSize": 4,
"listIndentation": 1, "listIndentation": 1,
"frontmatterType": "-",
"theme": "light", "theme": "light",