mirror of
https://github.com/marktext/marktext.git
synced 2025-05-10 03:02:04 +08:00
feat: handle backlash
This commit is contained in:
parent
ea1c1d0b0b
commit
6bb9d6c46e
4
TODO.md
4
TODO.md
@ -5,12 +5,12 @@
|
|||||||
- [x] 段落和换行,两个或两个以上的空格再敲回车,或插入一个\<br/\>
|
- [x] 段落和换行,两个或两个以上的空格再敲回车,或插入一个\<br/\>
|
||||||
- [x] 标题,支持 atx 形式的标题,在行首插入 1 到 6 个 #,会生成对应的 h1~6 h 标签。在敲回车后再转换成 HTML,但是在编辑标题的时候,显示会加粗。标题支持嵌套其他 markdown 样式。支持嵌套的样式包括加粗、斜体、行内代码、链接、图片。
|
- [x] 标题,支持 atx 形式的标题,在行首插入 1 到 6 个 #,会生成对应的 h1~6 h 标签。在敲回车后再转换成 HTML,但是在编辑标题的时候,显示会加粗。标题支持嵌套其他 markdown 样式。支持嵌套的样式包括加粗、斜体、行内代码、链接、图片。
|
||||||
- [x] 区块引用 Blockquotes,每行前面都加上 > ,支持嵌套区块引用,支持嵌套其他 markdown 语法,比如标题、列表、代码区块。区块引用会生成 blockquote 标签。
|
- [x] 区块引用 Blockquotes,每行前面都加上 > ,支持嵌套区块引用,支持嵌套其他 markdown 语法,比如标题、列表、代码区块。区块引用会生成 blockquote 标签。
|
||||||
- [x] 列表,有序列表和无需列表。无序列表使用 *、+、- 作为列表标记。有序列表使用数字加一个英文句点来标记。列表支持嵌套列表。列表支持嵌套区块引用,但仅限于行首,支持嵌套代码区块,但仅限于行首,支持其他 markdown 语法嵌套。
|
- [x] 列表,有序列表和无序列表。无序列表使用 *、+、- 作为列表标记。有序列表使用数字加一个英文句点来标记。列表支持嵌套列表。列表支持嵌套区块引用,但仅限于行首,支持嵌套代码区块,但仅限于行首,支持其他 markdown 语法嵌套。
|
||||||
- [x] 代码区块,代码区块中的 markdown 语法不再被转换。
|
- [x] 代码区块,代码区块中的 markdown 语法不再被转换。
|
||||||
- [x] 分割线,你可以在一行中使用三个以上的 *、-、_ 来创建分割线。
|
- [x] 分割线,你可以在一行中使用三个以上的 *、-、_ 来创建分割线。
|
||||||
- [x] 链接,markdown 支持两种形式的链接,行内式、参考式。
|
- [x] 链接,markdown 支持两种形式的链接,行内式、参考式。
|
||||||
- [ ] 图片,markdown 支持两种形式的图片,行内式、参考式。
|
- [ ] 图片,markdown 支持两种形式的图片,行内式、参考式。
|
||||||
- [x] Markdown 中使用\*、\_ 来表示强调,使用一个用 em 标签,使用两个用 strong 标签,如果\*、\_ 两边都(?)有空白的话,会被当做普通的符号。
|
- [x] Markdown 中使用\*、\_ 来表示强调,使用一个用 em 标签,使用两个用 strong 标签,如果\*、\_ 内侧有空白的话,会被当做普通的符号。
|
||||||
- [x] 代码,如果标记一小段代码,可以用反引号标记:\`。如果文字中已经有反引号,那么使用两个反引号。
|
- [x] 代码,如果标记一小段代码,可以用反引号标记:\`。如果文字中已经有反引号,那么使用两个反引号。
|
||||||
- [x] 简单链接、自动连接,使用\<\>包裹的链接会被转换为a 标签,还可以自动识别链接。
|
- [x] 简单链接、自动连接,使用\<\>包裹的链接会被转换为a 标签,还可以自动识别链接。
|
||||||
- [ ] 反斜线 \ 可以对如下字符转义:
|
- [ ] 反斜线 \ 可以对如下字符转义:
|
||||||
|
@ -63,7 +63,9 @@ export const CLASS_OR_ID = genUpper2LowerKeyHash([
|
|||||||
'AG_LANGUAGE',
|
'AG_LANGUAGE',
|
||||||
'AG_LANGUAGE_INPUT',
|
'AG_LANGUAGE_INPUT',
|
||||||
'AG_TEMP',
|
'AG_TEMP',
|
||||||
'AG_LINK_IN_BRACKET'
|
'AG_LINK_IN_BRACKET',
|
||||||
|
'AG_BACKLASH',
|
||||||
|
'AG_BUG' // for remove bug
|
||||||
])
|
])
|
||||||
|
|
||||||
export const codeMirrorConfig = {
|
export const codeMirrorConfig = {
|
||||||
|
@ -157,6 +157,10 @@ span[role="link"], a[role="link"] {
|
|||||||
color: #708;
|
color: #708;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
.ag-backlash {
|
||||||
|
text-decoration: none;
|
||||||
|
color: rgb(51, 51, 51);
|
||||||
|
}
|
||||||
.ag-warn {
|
.ag-warn {
|
||||||
color: #000;
|
color: #000;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
findOutMostParagraph, findNearestParagraph, isFirstChildElement,
|
findOutMostParagraph, findNearestParagraph, isFirstChildElement,
|
||||||
isOnlyChildElement
|
isOnlyChildElement
|
||||||
} from '../utils/domManipulate'
|
} from '../utils/domManipulate'
|
||||||
|
import { isEven } from '../utils'
|
||||||
import {
|
import {
|
||||||
LOWERCASE_TAGS,
|
LOWERCASE_TAGS,
|
||||||
CLASS_OR_ID,
|
CLASS_OR_ID,
|
||||||
@ -20,14 +20,14 @@ const fragments = [
|
|||||||
'^`{3,}[^`]*',
|
'^`{3,}[^`]*',
|
||||||
'^#{1,6}', // Header
|
'^#{1,6}', // Header
|
||||||
'(\\*{2}|_{2})(?:[^\\s]|[^\\s].*[^\\s])\\1', // strong
|
'(\\*{2}|_{2})(?:[^\\s]|[^\\s].*[^\\s])\\1', // strong
|
||||||
'(\\*{1}|_{1})(?:[^\\s]|[^\\s].*[^\\s])\\2', // em
|
'\\\\*(\\*{1}|_{1})(?:[^\\s]|[^\\s].*[^\\s])\\\\*\\2', // em
|
||||||
'(`{1,3})([^`]+?|.{2,})\\3', // inline code
|
'(`{1,3})([^`]+?|.{2,})\\3', // inline code
|
||||||
'\\[[^\\[\\]]+\\]\\(.*?\\)', // link
|
'\\[[^\\[\\]]+\\]\\(.*?\\)', // link
|
||||||
'\\[\\]\\([^\\(\\)]*?\\)', // no text link
|
'\\[\\]\\([^\\(\\)]*?\\)', // no text link
|
||||||
':[^:]+?:', // emoji
|
':[^:]+?:', // emoji
|
||||||
'~{2}[^~]+~{2}', // line through
|
'~{2}[^~]+~{2}', // line through
|
||||||
'https?://[^\\s]+(?=\\s|$)', // auto link
|
'https?://[^\\s]+(?=\\s|$)', // auto link
|
||||||
`\\\\(?=[${markedSymbol.join()}]{1})` // eslint-disable-line no-useless-escape
|
`\\\\+(?=[${markedSymbol.join()}]{1})` // eslint-disable-line no-useless-escape
|
||||||
]
|
]
|
||||||
|
|
||||||
const CHOP_REG = new RegExp(fragments.join('|'), 'g') // eslint-disable-line no-useless-escape
|
const CHOP_REG = new RegExp(fragments.join('|'), 'g') // eslint-disable-line no-useless-escape
|
||||||
@ -38,8 +38,8 @@ const HEAD_REG = /^#{1,6}/
|
|||||||
|
|
||||||
const STRONG_REG_G = /^(\*{2}|_{2})([^\s]|[^\s].*[^\s])(\1)/g
|
const STRONG_REG_G = /^(\*{2}|_{2})([^\s]|[^\s].*[^\s])(\1)/g
|
||||||
const STRONG_REG = /^(\*{2}|_{2})(?:[^\s]|[^\s].*[^\s])\1/
|
const STRONG_REG = /^(\*{2}|_{2})(?:[^\s]|[^\s].*[^\s])\1/
|
||||||
const EM_REG_G = /^(\*{1}|_{1})([^\s]|[^\s].*[^\s])(\1)/g
|
const EM_REG_G = /^(\\*)(\*{1}|_{1})([^\s]|[^\s].*?[^\s])(\\*)(\2)/g
|
||||||
const EM_REG = /^(\*{1}|_{1})(?:[^\s]|[^\s].*[^\s])\1/
|
const EM_REG = /^(?:\\*)(\*{1}|_{1})(?:[^\s]|[^\s].*[^\s])(?:\\*)\1/
|
||||||
|
|
||||||
const INLINE_CODE_REG_G = /^(`{1,3})([^`]+?|.{2,})(\1)/g
|
const INLINE_CODE_REG_G = /^(`{1,3})([^`]+?|.{2,})(\1)/g
|
||||||
const INLINE_CODE_REG = /^(`{1,3})([^`]+?|.{2,})(\1)/
|
const INLINE_CODE_REG = /^(`{1,3})([^`]+?|.{2,})(\1)/
|
||||||
@ -58,6 +58,9 @@ const HR_REG_G = /(^\*{3,}|^-{3,}|^_{3,})/g
|
|||||||
const HR_REG = /^\*{3,}|^-{3,}|^_{3,}/
|
const HR_REG = /^\*{3,}|^-{3,}|^_{3,}/
|
||||||
const CODE_BLOCK_G = /(^`{3,})([^`]*)/g
|
const CODE_BLOCK_G = /(^`{3,})([^`]*)/g
|
||||||
const CODE_BLOCK = /^`{3,}[^`]*/
|
const CODE_BLOCK = /^`{3,}[^`]*/
|
||||||
|
const BACKLASH_REG_G = new RegExp('^(\\\\+)', 'g')
|
||||||
|
const BACKLASH_REG = new RegExp('^\\\\+', 'i')
|
||||||
|
|
||||||
// const SIMPLE_LINK_G = /(<)([^<>]+?)(>)/g
|
// const SIMPLE_LINK_G = /(<)([^<>]+?)(>)/g
|
||||||
// const SIMPLE_LINK = /<[^<>]+?>/g
|
// const SIMPLE_LINK = /<[^<>]+?>/g
|
||||||
const LINE_BREAK_BLOCK_REG = /^(?:`{3,}([^`]*))|[\*\-\_]{3,}/ // eslint-disable-line no-useless-escape
|
const LINE_BREAK_BLOCK_REG = /^(?:`{3,}([^`]*))|[\*\-\_]{3,}/ // eslint-disable-line no-useless-escape
|
||||||
@ -70,6 +73,26 @@ const CHOP_HEADER_REG = /^([*+-]\s(?:\[\s\]\s)?|>\s*|\d+\.\s)/
|
|||||||
const conflict = (arr1, arr2) => {
|
const conflict = (arr1, arr2) => {
|
||||||
return !(arr1[1] < arr2[0] || arr2[1] < arr1[0])
|
return !(arr1[1] < arr2[0] || arr2[1] < arr1[0])
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* [backlash => html]
|
||||||
|
* examples:
|
||||||
|
* `\` => `<a href="#" class="${className}">\</a>`
|
||||||
|
* `\\` => `<a href="#" class="${className}">\</a>\`
|
||||||
|
*/
|
||||||
|
const backlash2html = (backlashes, className) => {
|
||||||
|
const chunks = backlashes.split('')
|
||||||
|
const len = chunks.length
|
||||||
|
let i
|
||||||
|
let result = ''
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (isEven(i)) {
|
||||||
|
result += `<a href="#" class="${className}">${chunks[i]}<a>`
|
||||||
|
} else {
|
||||||
|
result += `<a href="#" class="${CLASS_OR_ID['AG_BACKLASH']}">${chunks[i]}</a>`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `${result}<a class="${CLASS_OR_ID['AG_BUG']}"></a>` // the extral a tag for fix the bug.
|
||||||
|
}
|
||||||
|
|
||||||
const chunk2html = ({ chunk, index, lastIndex }, { start, end } = {}, outerClsssName) => {
|
const chunk2html = ({ chunk, index, lastIndex }, { start, end } = {}, outerClsssName) => {
|
||||||
// if no positionState provided, no conflict.
|
// if no positionState provided, no conflict.
|
||||||
@ -97,12 +120,23 @@ const chunk2html = ({ chunk, index, lastIndex }, { start, end } = {}, outerClsss
|
|||||||
|
|
||||||
// handle emphasize
|
// handle emphasize
|
||||||
if (EM_REG.test(chunk)) {
|
if (EM_REG.test(chunk)) {
|
||||||
return chunk.replace(EM_REG_G, (match, p1, p2, p3) => {
|
console.log('em')
|
||||||
return (
|
return chunk.replace(EM_REG_G, (match, p1, p2, p3, p4, p5) => {
|
||||||
`<a href="#" class="${className}">${p1}</a>` +
|
console.log(`p1: ${p1}, p2: ${p2}, p3: ${p3}, p4: ${p4}, p5: ${p5}`)
|
||||||
`<em>${markedText2Html(p2, undefined, className, 'inline')}</em>` +
|
if (isEven(p1.length) && isEven(p4.length)) {
|
||||||
`<a href="#" class="${className}">${p3}</a>`
|
return (
|
||||||
)
|
backlash2html(p1, className) +
|
||||||
|
`<a href="#" class="${className}">${p2}</a>` +
|
||||||
|
`<em>${markedText2Html(p3, undefined, className, 'inline')}${backlash2html(p4, className)}</em>` +
|
||||||
|
`<a href="#" class="${className}">${p5}</a>`
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
`${backlash2html(p1, className)}${p2}` +
|
||||||
|
`${markedText2Html(p3, undefined, className, 'inline')}` +
|
||||||
|
`${backlash2html(p4, className)}${p5}`
|
||||||
|
)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// handle inline code: markdown text: `code`
|
// handle inline code: markdown text: `code`
|
||||||
@ -209,6 +243,12 @@ const chunk2html = ({ chunk, index, lastIndex }, { start, end } = {}, outerClsss
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (BACKLASH_REG.test(chunk)) {
|
||||||
|
return chunk.replace(BACKLASH_REG_G, (match, p1) => {
|
||||||
|
return backlash2html(p1, className)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// handle picture
|
// handle picture
|
||||||
// TODO
|
// TODO
|
||||||
// handle auto link: markdown text: `<this is a auto link>`
|
// handle auto link: markdown text: `<this is a auto link>`
|
||||||
|
@ -19,6 +19,9 @@ export const getUniqueId = set => {
|
|||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const isOdd = number => Math.abs(number) % 2 === 1
|
||||||
|
export const isEven = number => Math.abs(number) % 2 === 0
|
||||||
|
|
||||||
// https://github.com/jashkenas/underscore
|
// https://github.com/jashkenas/underscore
|
||||||
export const throttle = (func, wait = 50) => {
|
export const throttle = (func, wait = 50) => {
|
||||||
let context
|
let context
|
||||||
|
Loading…
Reference in New Issue
Block a user