mirror of
https://github.com/marktext/marktext.git
synced 2025-05-03 07:01:41 +08:00
Complete TOML and JSON front matter (#1402)
* Complete TOML and JSON front matter * Add frontmatter settings
This commit is contained in:
parent
60a12ae221
commit
ddf9c50a42
@ -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
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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+|$)/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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('')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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',
|
||||||
|
@ -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: '{'
|
||||||
|
}]
|
||||||
|
@ -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: {
|
||||||
|
@ -35,6 +35,7 @@ const state = {
|
|||||||
preferHeadingStyle: 'atx',
|
preferHeadingStyle: 'atx',
|
||||||
tabSize: 4,
|
tabSize: 4,
|
||||||
listIndentation: 1,
|
listIndentation: 1,
|
||||||
|
frontmatterType: '-',
|
||||||
|
|
||||||
theme: 'light',
|
theme: 'light',
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
"preferHeadingStyle": "atx",
|
"preferHeadingStyle": "atx",
|
||||||
"tabSize": 4,
|
"tabSize": 4,
|
||||||
"listIndentation": 1,
|
"listIndentation": 1,
|
||||||
|
"frontmatterType": "-",
|
||||||
|
|
||||||
"theme": "light",
|
"theme": "light",
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user