mirror of
https://github.com/marktext/marktext.git
synced 2025-05-02 19:59:41 +08:00
feat: add code block line numbers
This commit is contained in:
parent
b4af38b94d
commit
a028a7c2bb
@ -31,6 +31,7 @@ Preferences can be controlled and modified in the settings window or via the `pr
|
|||||||
| textDirection | String | ltr | The writing text direction, optional value: `ltr` or `rtl` |
|
| textDirection | String | ltr | The writing text direction, optional value: `ltr` or `rtl` |
|
||||||
| codeFontSize | Number | 14 | Font size on code block, the range is 12 ~ 28 |
|
| codeFontSize | Number | 14 | Font size on code block, the range is 12 ~ 28 |
|
||||||
| codeFontFamily | String | `DejaVu Sans Mono` | Code font family |
|
| codeFontFamily | String | `DejaVu Sans Mono` | Code font family |
|
||||||
|
| codeBlockLineNumbers | Boolean | true | Whether to show the line numbers in code block |
|
||||||
| trimUnnecessaryCodeBlockEmptyLines | Boolean | true | Whether to trim the beginning and end empty line in Code block |
|
| trimUnnecessaryCodeBlockEmptyLines | Boolean | true | Whether to trim the beginning and end empty line in Code block |
|
||||||
| hideQuickInsertHint | Boolean | false | Hide hint for quickly creating paragraphs |
|
| hideQuickInsertHint | Boolean | false | Hide hint for quickly creating paragraphs |
|
||||||
| imageDropAction | String | folder | The default behavior after paste or drag the image to Mark Text, upload it to the image cloud (if configured), move to the specified folder, insert the path |
|
| imageDropAction | String | folder | The default behavior after paste or drag the image to Mark Text, upload it to the image cloud (if configured), move to the specified folder, insert the path |
|
||||||
|
@ -94,6 +94,11 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"pattern": "^[_A-z0-9]+((-|\\s)*[_A-z0-9])*$"
|
"pattern": "^[_A-z0-9]+((-|\\s)*[_A-z0-9])*$"
|
||||||
},
|
},
|
||||||
|
"codeBlockLineNumbers": {
|
||||||
|
"description": "Editor--Whether to show the line numbers",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
"trimUnnecessaryCodeBlockEmptyLines": {
|
"trimUnnecessaryCodeBlockEmptyLines": {
|
||||||
"description": "Editor--Trim the beginning and ending empty lines in code block",
|
"description": "Editor--Trim the beginning and ending empty lines in code block",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
@ -1107,3 +1107,49 @@ span.ag-reference-link {
|
|||||||
.vega-embed {
|
.vega-embed {
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"].line-numbers {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 2.5em;
|
||||||
|
counter-reset: linenumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"].line-numbers > code {
|
||||||
|
position: relative;
|
||||||
|
white-space: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure:not(.ag-active) pre[class*="language-"].line-numbers {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers .line-numbers-rows {
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
top: 0;
|
||||||
|
font-size: 100%;
|
||||||
|
left: -2.5em;
|
||||||
|
width: 2.5em; /* works for line-numbers below 1000 lines */
|
||||||
|
letter-spacing: -1px;
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers-rows > span {
|
||||||
|
pointer-events: none;
|
||||||
|
display: block;
|
||||||
|
counter-increment: linenumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers-rows > span:before {
|
||||||
|
content: counter(linenumber);
|
||||||
|
color: var(--editorColor30);
|
||||||
|
display: block;
|
||||||
|
padding-right: .8em;
|
||||||
|
text-align: right;
|
||||||
|
transform: scale(.8);
|
||||||
|
position: relative;
|
||||||
|
top: .05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -254,6 +254,7 @@ export const MUYA_DEFAULT_OPTION = {
|
|||||||
bulletListMarker: '-',
|
bulletListMarker: '-',
|
||||||
orderListDelimiter: '.',
|
orderListDelimiter: '.',
|
||||||
tabSize: 4,
|
tabSize: 4,
|
||||||
|
codeBlockLineNumbers: true,
|
||||||
// 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: '-',
|
frontmatterType: '-',
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { CLASS_OR_ID } from '../../../config'
|
import { CLASS_OR_ID } from '../../../config'
|
||||||
import { renderTableTools } from './renderToolBar'
|
import { renderTableTools } from './renderToolBar'
|
||||||
import { renderEditIcon } from './renderContainerEditIcon'
|
import { renderEditIcon } from './renderContainerEditIcon'
|
||||||
|
import renderLineNumberRows from './renderLineNumber'
|
||||||
import { renderLeftBar, renderBottomBar } from './renderTableDargBar'
|
import { renderLeftBar, renderBottomBar } from './renderTableDargBar'
|
||||||
import { h } from '../snabbdom'
|
import { h } from '../snabbdom'
|
||||||
|
|
||||||
@ -45,8 +46,17 @@ export default function renderContainerBlock (parent, block, activeBlocks, match
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/code|pre/.test(type) && typeof lang === 'string' && !!lang) {
|
if (/code|pre/.test(type)) {
|
||||||
selector += `.language-${lang.replace(/[#.]{1}/g, '')}`
|
if (typeof lang === 'string' && !!lang) {
|
||||||
|
selector += `.language-${lang.replace(/[#.]{1}/g, '')}`
|
||||||
|
}
|
||||||
|
if (this.muya.options.codeBlockLineNumbers) {
|
||||||
|
if (type === 'pre') {
|
||||||
|
selector += '.line-numbers'
|
||||||
|
} else {
|
||||||
|
children.unshift(renderLineNumberRows(block.children[0]))
|
||||||
|
}
|
||||||
|
}
|
||||||
Object.assign(data.attrs, { spellcheck: 'false' })
|
Object.assign(data.attrs, { spellcheck: 'false' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
src/muya/lib/parser/render/renderBlock/renderLineNumber.js
Normal file
22
src/muya/lib/parser/render/renderBlock/renderLineNumber.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { h } from '../snabbdom'
|
||||||
|
|
||||||
|
const NEW_LINE_EXP = /\n(?!$)/g
|
||||||
|
|
||||||
|
const renderLineNumberRows = codeContent => {
|
||||||
|
const { text } = codeContent
|
||||||
|
const match = text.match(NEW_LINE_EXP)
|
||||||
|
let linesNum = match ? match.length + 1 : 1
|
||||||
|
if (text.endsWith('\n')) {
|
||||||
|
linesNum++
|
||||||
|
}
|
||||||
|
const data = {
|
||||||
|
attrs: {
|
||||||
|
'aria-hidden': true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const children = [...new Array(linesNum)].map(() => h('span'))
|
||||||
|
|
||||||
|
return h('span.line-numbers-rows', data, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default renderLineNumberRows
|
@ -140,6 +140,7 @@ export default {
|
|||||||
fontSize: state => state.preferences.fontSize,
|
fontSize: state => state.preferences.fontSize,
|
||||||
codeFontSize: state => state.preferences.codeFontSize,
|
codeFontSize: state => state.preferences.codeFontSize,
|
||||||
codeFontFamily: state => state.preferences.codeFontFamily,
|
codeFontFamily: state => state.preferences.codeFontFamily,
|
||||||
|
codeBlockLineNumbers: state => state.preferences.codeBlockLineNumbers,
|
||||||
trimUnnecessaryCodeBlockEmptyLines: state => state.preferences.trimUnnecessaryCodeBlockEmptyLines,
|
trimUnnecessaryCodeBlockEmptyLines: state => state.preferences.trimUnnecessaryCodeBlockEmptyLines,
|
||||||
editorFontFamily: state => state.preferences.editorFontFamily,
|
editorFontFamily: state => state.preferences.editorFontFamily,
|
||||||
hideQuickInsertHint: state => state.preferences.hideQuickInsertHint,
|
hideQuickInsertHint: state => state.preferences.hideQuickInsertHint,
|
||||||
@ -312,6 +313,12 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
codeBlockLineNumbers: function (value, oldValue) {
|
||||||
|
const { editor } = this
|
||||||
|
if (value !== oldValue && editor) {
|
||||||
|
editor.setOptions({ codeBlockLineNumbers: value }, true)
|
||||||
|
}
|
||||||
|
},
|
||||||
codeFontFamily: function (value, oldValue) {
|
codeFontFamily: function (value, oldValue) {
|
||||||
if (value !== oldValue) {
|
if (value !== oldValue) {
|
||||||
addCommonStyle({
|
addCommonStyle({
|
||||||
@ -443,6 +450,7 @@ export default {
|
|||||||
tabSize,
|
tabSize,
|
||||||
fontSize,
|
fontSize,
|
||||||
lineHeight,
|
lineHeight,
|
||||||
|
codeBlockLineNumbers,
|
||||||
listIndentation,
|
listIndentation,
|
||||||
frontmatterType,
|
frontmatterType,
|
||||||
superSubScript,
|
superSubScript,
|
||||||
@ -485,6 +493,7 @@ export default {
|
|||||||
tabSize,
|
tabSize,
|
||||||
fontSize,
|
fontSize,
|
||||||
lineHeight,
|
lineHeight,
|
||||||
|
codeBlockLineNumbers,
|
||||||
listIndentation,
|
listIndentation,
|
||||||
frontmatterType,
|
frontmatterType,
|
||||||
superSubScript,
|
superSubScript,
|
||||||
|
@ -39,6 +39,11 @@
|
|||||||
:value="codeFontFamily"
|
:value="codeFontFamily"
|
||||||
:onChange="value => onSelectChange('codeFontFamily', value)"
|
:onChange="value => onSelectChange('codeFontFamily', value)"
|
||||||
></font-text-box>
|
></font-text-box>
|
||||||
|
<bool
|
||||||
|
description="Whether to show the code block line numbers."
|
||||||
|
:bool="codeBlockLineNumbers"
|
||||||
|
:onChange="value => onSelectChange('codeBlockLineNumbers', value)"
|
||||||
|
></bool>
|
||||||
<bool
|
<bool
|
||||||
description="Trim the beginning and ending empty lines in code block when open markdown."
|
description="Trim the beginning and ending empty lines in code block when open markdown."
|
||||||
:bool="trimUnnecessaryCodeBlockEmptyLines"
|
:bool="trimUnnecessaryCodeBlockEmptyLines"
|
||||||
@ -148,6 +153,7 @@ export default {
|
|||||||
textDirection: state => state.preferences.textDirection,
|
textDirection: state => state.preferences.textDirection,
|
||||||
codeFontSize: state => state.preferences.codeFontSize,
|
codeFontSize: state => state.preferences.codeFontSize,
|
||||||
codeFontFamily: state => state.preferences.codeFontFamily,
|
codeFontFamily: state => state.preferences.codeFontFamily,
|
||||||
|
codeBlockLineNumbers: state => state.preferences.codeBlockLineNumbers,
|
||||||
trimUnnecessaryCodeBlockEmptyLines: state => state.preferences.trimUnnecessaryCodeBlockEmptyLines,
|
trimUnnecessaryCodeBlockEmptyLines: state => state.preferences.trimUnnecessaryCodeBlockEmptyLines,
|
||||||
hideQuickInsertHint: state => state.preferences.hideQuickInsertHint,
|
hideQuickInsertHint: state => state.preferences.hideQuickInsertHint,
|
||||||
hideLinkPopup: state => state.preferences.hideLinkPopup,
|
hideLinkPopup: state => state.preferences.hideLinkPopup,
|
||||||
|
@ -19,6 +19,7 @@ const state = {
|
|||||||
lineHeight: 1.6,
|
lineHeight: 1.6,
|
||||||
codeFontSize: 14,
|
codeFontSize: 14,
|
||||||
codeFontFamily: 'DejaVu Sans Mono',
|
codeFontFamily: 'DejaVu Sans Mono',
|
||||||
|
codeBlockLineNumbers: true,
|
||||||
trimUnnecessaryCodeBlockEmptyLines: true,
|
trimUnnecessaryCodeBlockEmptyLines: true,
|
||||||
editorLineWidth: '',
|
editorLineWidth: '',
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"lineHeight": 1.6,
|
"lineHeight": 1.6,
|
||||||
"codeFontSize": 14,
|
"codeFontSize": 14,
|
||||||
"codeFontFamily": "DejaVu Sans Mono",
|
"codeFontFamily": "DejaVu Sans Mono",
|
||||||
|
"codeBlockLineNumbers": true,
|
||||||
"trimUnnecessaryCodeBlockEmptyLines": true,
|
"trimUnnecessaryCodeBlockEmptyLines": true,
|
||||||
"editorLineWidth": "",
|
"editorLineWidth": "",
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user