mirror of
https://github.com/marktext/marktext.git
synced 2025-05-02 03:11:29 +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) |
|
||||
| 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
|
||||
|
||||
|
@ -165,6 +165,15 @@
|
||||
4
|
||||
]
|
||||
},
|
||||
"frontmatterType": {
|
||||
"description": "Markdown--The frontmatter type",
|
||||
"enum": [
|
||||
"-",
|
||||
"+",
|
||||
";",
|
||||
"{"
|
||||
]
|
||||
},
|
||||
"theme": {
|
||||
"description": "Theme--Select the theme used in Mark Text",
|
||||
"type": "string"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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+|$)/
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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('')
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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: '{'
|
||||
}]
|
||||
|
@ -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: {
|
||||
|
@ -35,6 +35,7 @@ const state = {
|
||||
preferHeadingStyle: 'atx',
|
||||
tabSize: 4,
|
||||
listIndentation: 1,
|
||||
frontmatterType: '-',
|
||||
|
||||
theme: 'light',
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
"preferHeadingStyle": "atx",
|
||||
"tabSize": 4,
|
||||
"listIndentation": 1,
|
||||
"frontmatterType": "-",
|
||||
|
||||
"theme": "light",
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user