mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 17:56:25 +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 eventEmitter from 'browser/main/lib/eventEmitter'
|
||||
import fs from 'fs'
|
||||
|
||||
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
|
||||
}
|
||||
import htmlTextHelper from 'browser/lib/htmlTextHelper'
|
||||
|
||||
const { remote } = require('electron')
|
||||
const { app } = remote
|
||||
@@ -241,6 +227,13 @@ export default class MarkdownPreview extends React.Component {
|
||||
let { value, theme, indentSize, codeBlockTheme } = this.props
|
||||
|
||||
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)
|
||||
|
||||
_.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)
|
||||
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
||||
CodeMirror.requireMode(syntax.mode, () => {
|
||||
let content = decodeHTMLEntities(el.innerHTML)
|
||||
let content = htmlTextHelper.decodeEntities(el.innerHTML)
|
||||
el.innerHTML = ''
|
||||
el.parentNode.className += ` cm-s-${codeBlockTheme} CodeMirror`
|
||||
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) => {
|
||||
Raphael.setWindow(this.getWindow())
|
||||
try {
|
||||
let diagram = flowchart.parse(decodeHTMLEntities(el.innerHTML))
|
||||
let diagram = flowchart.parse(htmlTextHelper.decodeEntities(el.innerHTML))
|
||||
el.innerHTML = ''
|
||||
diagram.drawSVG(el, opts)
|
||||
_.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) => {
|
||||
Raphael.setWindow(this.getWindow())
|
||||
try {
|
||||
let diagram = SequenceDiagram.parse(decodeHTMLEntities(el.innerHTML))
|
||||
let diagram = SequenceDiagram.parse(htmlTextHelper.decodeEntities(el.innerHTML))
|
||||
el.innerHTML = ''
|
||||
diagram.drawSVG(el, {theme: 'simple'})
|
||||
_.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