Skip to content

Commit

Permalink
Complete TOML and JSON front matter (marktext#1402)
Browse files Browse the repository at this point in the history
* Complete TOML and JSON front matter

* Add frontmatter settings
  • Loading branch information
fxha authored Oct 2, 2019
1 parent 60a12ae commit ddf9c50
Show file tree
Hide file tree
Showing 13 changed files with 123 additions and 11 deletions.
2 changes: 2 additions & 0 deletions docs/PREFERENCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
9 changes: 9 additions & 0 deletions src/main/preferences/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,15 @@
4
]
},
"frontmatterType": {
"description": "Markdown--The frontmatter type",
"enum": [
"-",
"+",
";",
"{"
]
},
"theme": {
"description": "Theme--Select the theme used in Mark Text",
"type": "string"
Expand Down
1 change: 1 addition & 0 deletions src/muya/lib/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 26 additions & 2 deletions src/muya/lib/contentState/paragraphCtrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/muya/lib/parser/marked/blockRules.js
Original file line number Diff line number Diff line change
Expand Up @@ -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+|$)/
}

Expand Down
22 changes: 20 additions & 2 deletions src/muya/lib/parser/marked/lexer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
26 changes: 24 additions & 2 deletions src/muya/lib/utils/exportMarkdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -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('')
}

Expand Down
5 changes: 3 additions & 2 deletions src/muya/lib/utils/importMarkdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions src/renderer/components/editorWithTabs/editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -323,6 +330,7 @@ export default {
orderListDelimiter,
tabSize,
listIndentation,
frontmatterType,
hideQuickInsertHint,
editorLineWidth,
theme
Expand Down Expand Up @@ -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',
Expand Down
14 changes: 14 additions & 0 deletions src/renderer/prefComponents/markdown/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: '{'
}]
13 changes: 11 additions & 2 deletions src/renderer/prefComponents/markdown/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand All @@ -52,7 +58,8 @@ import {
orderListDelimiterOptions,
preferHeadingStyleOptions,
tabSizeOptions,
listIndentationOptions
listIndentationOptions,
frontmatterTypeOptions
} from './config'
export default {
Expand All @@ -66,6 +73,7 @@ export default {
this.preferHeadingStyleOptions = preferHeadingStyleOptions
this.tabSizeOptions = tabSizeOptions
this.listIndentationOptions = listIndentationOptions
this.frontmatterTypeOptions = frontmatterTypeOptions
return {}
},
computed: {
Expand All @@ -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: {
Expand Down
1 change: 1 addition & 0 deletions src/renderer/store/preferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const state = {
preferHeadingStyle: 'atx',
tabSize: 4,
listIndentation: 1,
frontmatterType: '-',

theme: 'light',

Expand Down
1 change: 1 addition & 0 deletions static/preference.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"preferHeadingStyle": "atx",
"tabSize": 4,
"listIndentation": 1,
"frontmatterType": "-",

"theme": "light",

Expand Down

0 comments on commit ddf9c50

Please sign in to comment.