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) |
| 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 |
| frontmatterType | String | `-` | The frontmatter type: `-` (YAML), `+` (TOML), `;` (JSON) or `{` (JSON) |
#### View

View File

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

View File

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

View File

@ -68,10 +68,33 @@ const paragraphCtrl = ContentState => {
ContentState.prototype.handleFrontMatter = function () {
const firstBlock = this.blocks[0]
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', {
functionType: 'frontmatter',
lang
lang,
style
})
const codeBlock = this.createBlock('code', {
lang
@ -626,6 +649,7 @@ const paragraphCtrl = ContentState => {
} else {
anchor = this.getAnchor(block)
}
// You can not insert paragraph before frontmatter
if (!anchor || anchor && anchor.functionType === 'frontmatter' && location === 'before') {
return

View File

@ -34,7 +34,7 @@ export const block = {
text: /^[^\n]+/,
// 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+|$)/
}

View File

@ -51,14 +51,32 @@ Lexer.prototype.token = function (src, top) {
let checked
// 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) {
cap = this.rules.frontmatter.exec(src)
if (this.checkFrontmatter && top && cap) {
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({
type: 'frontmatter',
text: cap[1]
text,
style,
lang
})
}
this.checkFrontmatter = false

View File

@ -192,12 +192,34 @@ class ExportMarkdown {
}
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 = []
result.push('---\n')
result.push(startToken)
for (const line of block.children[0].children) {
result.push(`${line.text}\n`)
}
result.push('---\n')
result.push(endToken)
return result.join('')
}

View File

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

View File

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

View File

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

View File

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

View File

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