feat: handle backlash

This commit is contained in:
Jocs 2017-11-24 17:02:05 +08:00
parent ea1c1d0b0b
commit 6bb9d6c46e
5 changed files with 63 additions and 14 deletions

View File

@ -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 标签,还可以自动识别链接。
- [ ] 反斜线 \ 可以对如下字符转义: - [ ] 反斜线 \ 可以对如下字符转义:

View File

@ -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 = {

View File

@ -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;

View File

@ -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>`

View File

@ -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