mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-14 10:16:26 +00:00
Merge pull request #341 from asmsuechan/fix-incorrect-tag-completion
Fix incorrect tag completion in code block
This commit is contained in:
@@ -8,21 +8,7 @@ import flowchart from 'flowchart'
|
|||||||
import SequenceDiagram from 'js-sequence-diagrams'
|
import SequenceDiagram from 'js-sequence-diagrams'
|
||||||
import eventEmitter from 'browser/main/lib/eventEmitter'
|
import eventEmitter from 'browser/main/lib/eventEmitter'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
import htmlTextHelper from 'browser/lib/htmlTextHelper'
|
||||||
function decodeHTMLEntities (text) {
|
|
||||||
var entities = [
|
|
||||||
['apos', '\''],
|
|
||||||
['amp', '&'],
|
|
||||||
['lt', '<'],
|
|
||||||
['gt', '>']
|
|
||||||
]
|
|
||||||
|
|
||||||
for (var i = 0, max = entities.length; i < max; ++i) {
|
|
||||||
text = text.replace(new RegExp('&' + entities[i][0] + ';', 'g'), entities[i][1])
|
|
||||||
}
|
|
||||||
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
|
|
||||||
const { remote } = require('electron')
|
const { remote } = require('electron')
|
||||||
const { app } = remote
|
const { app } = remote
|
||||||
@@ -241,6 +227,13 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
let { value, theme, indentSize, codeBlockTheme } = this.props
|
let { value, theme, indentSize, codeBlockTheme } = this.props
|
||||||
|
|
||||||
this.refs.root.contentWindow.document.body.setAttribute('data-theme', theme)
|
this.refs.root.contentWindow.document.body.setAttribute('data-theme', theme)
|
||||||
|
|
||||||
|
const codeBlocks = value.match(/(```)(.|[\n])*?(```)/g)
|
||||||
|
if (codeBlocks !== null) {
|
||||||
|
codeBlocks.forEach((codeBlock) => {
|
||||||
|
value = value.replace(codeBlock, htmlTextHelper.encodeEntities(codeBlock))
|
||||||
|
})
|
||||||
|
}
|
||||||
this.refs.root.contentWindow.document.body.innerHTML = markdown.render(value)
|
this.refs.root.contentWindow.document.body.innerHTML = markdown.render(value)
|
||||||
|
|
||||||
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.taskListItem'), (el) => {
|
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.taskListItem'), (el) => {
|
||||||
@@ -263,7 +256,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
let syntax = CodeMirror.findModeByName(el.className)
|
let syntax = CodeMirror.findModeByName(el.className)
|
||||||
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
||||||
CodeMirror.requireMode(syntax.mode, () => {
|
CodeMirror.requireMode(syntax.mode, () => {
|
||||||
let content = decodeHTMLEntities(el.innerHTML)
|
let content = htmlTextHelper.decodeEntities(el.innerHTML)
|
||||||
el.innerHTML = ''
|
el.innerHTML = ''
|
||||||
el.parentNode.className += ` cm-s-${codeBlockTheme} CodeMirror`
|
el.parentNode.className += ` cm-s-${codeBlockTheme} CodeMirror`
|
||||||
CodeMirror.runMode(content, syntax.mime, el, {
|
CodeMirror.runMode(content, syntax.mime, el, {
|
||||||
@@ -281,7 +274,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.flowchart'), (el) => {
|
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.flowchart'), (el) => {
|
||||||
Raphael.setWindow(this.getWindow())
|
Raphael.setWindow(this.getWindow())
|
||||||
try {
|
try {
|
||||||
let diagram = flowchart.parse(decodeHTMLEntities(el.innerHTML))
|
let diagram = flowchart.parse(htmlTextHelper.decodeEntities(el.innerHTML))
|
||||||
el.innerHTML = ''
|
el.innerHTML = ''
|
||||||
diagram.drawSVG(el, opts)
|
diagram.drawSVG(el, opts)
|
||||||
_.forEach(el.querySelectorAll('a'), (el) => {
|
_.forEach(el.querySelectorAll('a'), (el) => {
|
||||||
@@ -297,7 +290,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.sequence'), (el) => {
|
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.sequence'), (el) => {
|
||||||
Raphael.setWindow(this.getWindow())
|
Raphael.setWindow(this.getWindow())
|
||||||
try {
|
try {
|
||||||
let diagram = SequenceDiagram.parse(decodeHTMLEntities(el.innerHTML))
|
let diagram = SequenceDiagram.parse(htmlTextHelper.decodeEntities(el.innerHTML))
|
||||||
el.innerHTML = ''
|
el.innerHTML = ''
|
||||||
diagram.drawSVG(el, {theme: 'simple'})
|
diagram.drawSVG(el, {theme: 'simple'})
|
||||||
_.forEach(el.querySelectorAll('a'), (el) => {
|
_.forEach(el.querySelectorAll('a'), (el) => {
|
||||||
|
|||||||
43
browser/lib/htmlTextHelper.js
Normal file
43
browser/lib/htmlTextHelper.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* @fileoverview Text trimmer for html.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} text
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function decodeEntities (text) {
|
||||||
|
var entities = [
|
||||||
|
['apos', '\''],
|
||||||
|
['amp', '&'],
|
||||||
|
['lt', '<'],
|
||||||
|
['gt', '>'],
|
||||||
|
['#63', '\\?']
|
||||||
|
]
|
||||||
|
|
||||||
|
for (var i = 0, max = entities.length; i < max; ++i) {
|
||||||
|
text = text.replace(new RegExp(`&${entities[i][0]};`, 'g'), entities[i][1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
export function encodeEntities (text) {
|
||||||
|
const entities = [
|
||||||
|
['\'', 'apos'],
|
||||||
|
['<', 'lt'],
|
||||||
|
['>', 'gt'],
|
||||||
|
['\\?', '#63']
|
||||||
|
]
|
||||||
|
|
||||||
|
entities.forEach((entity) => {
|
||||||
|
text = text.replace(new RegExp(entity[0], 'g'), `&${entity[1]};`)
|
||||||
|
})
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
decodeEntities,
|
||||||
|
encodeEntities
|
||||||
|
}
|
||||||
52
tests/lib/html-text-helper-test.js
Normal file
52
tests/lib/html-text-helper-test.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* @fileoverview Unit test for browser/lib/htmlTextHelper
|
||||||
|
*/
|
||||||
|
const test = require('ava')
|
||||||
|
const htmlTextHelper = require('browser/lib/htmlTextHelper')
|
||||||
|
|
||||||
|
// Unit test
|
||||||
|
test('htmlTextHelper#decodeEntities should return encoded text (string)', t => {
|
||||||
|
// [input, expected]
|
||||||
|
const testCases = [
|
||||||
|
['<a href=', '<a href='],
|
||||||
|
['var test = 'test'', 'var test = \'test\''],
|
||||||
|
['<a href='https://boostnote.io'>Boostnote', '<a href=\'https://boostnote.io\'>Boostnote'],
|
||||||
|
['<\\\\?php\n var = 'hoge';', '<\\\\?php\n var = \'hoge\';'],
|
||||||
|
['&', '&']
|
||||||
|
]
|
||||||
|
|
||||||
|
testCases.forEach(testCase => {
|
||||||
|
const [input, expected] = testCase
|
||||||
|
t.is(htmlTextHelper.decodeEntities(input), expected, `Test for decodeEntities() input: ${input} expected: ${expected}`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('htmlTextHelper#decodeEntities() should return decoded text (string)', t => {
|
||||||
|
// [input, expected]
|
||||||
|
const testCases = [
|
||||||
|
['<a href=', '<a href='],
|
||||||
|
['var test = \'test\'', 'var test = 'test''],
|
||||||
|
['<a href=\'https://boostnote.io\'>Boostnote', '<a href='https://boostnote.io'>Boostnote'],
|
||||||
|
['<?php\n var = \'hoge\';', '<?php\n var = 'hoge';']
|
||||||
|
]
|
||||||
|
|
||||||
|
testCases.forEach(testCase => {
|
||||||
|
const [input, expected] = testCase
|
||||||
|
t.is(htmlTextHelper.encodeEntities(input), expected, `Test for encodeEntities() input: ${input} expected: ${expected}`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Integration test
|
||||||
|
test(t => {
|
||||||
|
const testCases = [
|
||||||
|
'var test = \'test\'',
|
||||||
|
'<a href=\'https://boostnote.io\'>Boostnote',
|
||||||
|
'<Component styleName=\'test\' />'
|
||||||
|
]
|
||||||
|
|
||||||
|
testCases.forEach(testCase => {
|
||||||
|
const encodedText = htmlTextHelper.encodeEntities(testCase)
|
||||||
|
const decodedText = htmlTextHelper.decodeEntities(encodedText)
|
||||||
|
t.is(decodedText, testCase, 'Integration test through encodedText() and decodedText()')
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user