mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 09:46:22 +00:00
Merge remote-tracking branch 'BoostIO/master'
This commit is contained in:
@@ -5,6 +5,8 @@ import CodeMirror from 'codemirror'
|
||||
import 'codemirror-mode-elixir'
|
||||
import attachmentManagement from 'browser/main/lib/dataApi/attachmentManagement'
|
||||
import convertModeName from 'browser/lib/convertModeName'
|
||||
import { options, TableEditor } from '@susisu/mte-kernel'
|
||||
import TextEditorInterface from 'browser/lib/TextEditorInterface'
|
||||
import eventEmitter from 'browser/main/lib/eventEmitter'
|
||||
import iconv from 'iconv-lite'
|
||||
import crypto from 'crypto'
|
||||
@@ -48,6 +50,8 @@ export default class CodeEditor extends React.Component {
|
||||
}
|
||||
this.searchHandler = (e, msg) => this.handleSearch(msg)
|
||||
this.searchState = null
|
||||
|
||||
this.formatTable = () => this.handleFormatTable()
|
||||
}
|
||||
|
||||
handleSearch (msg) {
|
||||
@@ -81,6 +85,10 @@ export default class CodeEditor extends React.Component {
|
||||
})
|
||||
}
|
||||
|
||||
handleFormatTable () {
|
||||
this.tableEditor.formatAll(options({textWidthOptions: {}}))
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
const { rulers, enableRulers } = this.props
|
||||
const expandSnippet = this.expandSnippet.bind(this)
|
||||
@@ -113,7 +121,12 @@ export default class CodeEditor extends React.Component {
|
||||
dragDrop: false,
|
||||
foldGutter: true,
|
||||
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
|
||||
autoCloseBrackets: true,
|
||||
autoCloseBrackets: {
|
||||
pairs: '()[]{}\'\'""$$**``',
|
||||
triples: '```"""\'\'\'',
|
||||
explode: '[]{}``$$',
|
||||
override: true
|
||||
},
|
||||
extraKeys: {
|
||||
Tab: function (cm) {
|
||||
const cursor = cm.getCursor()
|
||||
@@ -182,6 +195,9 @@ export default class CodeEditor extends React.Component {
|
||||
CodeMirror.Vim.defineEx('wq', 'wq', this.quitEditor)
|
||||
CodeMirror.Vim.defineEx('qw', 'qw', this.quitEditor)
|
||||
CodeMirror.Vim.map('ZZ', ':q', 'normal')
|
||||
|
||||
this.tableEditor = new TableEditor(new TextEditorInterface(this.editor))
|
||||
eventEmitter.on('code:format-table', this.formatTable)
|
||||
}
|
||||
|
||||
expandSnippet (line, cursor, cm, snippets) {
|
||||
@@ -264,6 +280,8 @@ export default class CodeEditor extends React.Component {
|
||||
this.editor.off('scroll', this.scrollHandler)
|
||||
const editorTheme = document.getElementById('editorTheme')
|
||||
editorTheme.removeEventListener('load', this.loadStyleHandler)
|
||||
|
||||
eventEmitter.off('code:format-table', this.formatTable)
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps, prevState) {
|
||||
|
||||
@@ -7,7 +7,9 @@ import 'codemirror-mode-elixir'
|
||||
import consts from 'browser/lib/consts'
|
||||
import Raphael from 'raphael'
|
||||
import flowchart from 'flowchart'
|
||||
import mermaidRender from './render/MermaidRender'
|
||||
import SequenceDiagram from 'js-sequence-diagrams'
|
||||
import Chart from 'chart.js'
|
||||
import eventEmitter from 'browser/main/lib/eventEmitter'
|
||||
import htmlTextHelper from 'browser/lib/htmlTextHelper'
|
||||
import convertModeName from 'browser/lib/convertModeName'
|
||||
@@ -131,6 +133,25 @@ body p {
|
||||
`
|
||||
}
|
||||
|
||||
const scrollBarStyle = `
|
||||
::-webkit-scrollbar {
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
`
|
||||
const scrollBarDarkStyle = `
|
||||
::-webkit-scrollbar {
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
`
|
||||
|
||||
const { shell } = require('electron')
|
||||
const OSX = global.process.platform === 'darwin'
|
||||
|
||||
@@ -211,7 +232,20 @@ export default class MarkdownPreview extends React.Component {
|
||||
}
|
||||
|
||||
handleSaveAsMd () {
|
||||
this.exportAsDocument('md')
|
||||
this.exportAsDocument('md', (noteContent, exportTasks) => {
|
||||
let result = noteContent
|
||||
if (this.props && this.props.storagePath && this.props.noteKey) {
|
||||
const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(noteContent, this.props.storagePath)
|
||||
attachmentsAbsolutePaths.forEach((attachment) => {
|
||||
exportTasks.push({
|
||||
src: attachment,
|
||||
dst: attachmentManagement.DESTINATION_FOLDER
|
||||
})
|
||||
})
|
||||
result = attachmentManagement.removeStorageAndNoteReferences(noteContent, this.props.noteKey)
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
handleSaveAsHtml () {
|
||||
@@ -219,13 +253,18 @@ export default class MarkdownPreview extends React.Component {
|
||||
const {fontFamily, fontSize, codeBlockFontFamily, lineNumber, codeBlockTheme, scrollPastEnd, theme, allowCustomCSS, customCSS} = this.getStyleParams()
|
||||
|
||||
const inlineStyles = buildStyle(fontFamily, fontSize, codeBlockFontFamily, lineNumber, scrollPastEnd, theme, allowCustomCSS, customCSS)
|
||||
let body = this.markdown.render(escapeHtmlCharacters(noteContent))
|
||||
let body = this.markdown.render(escapeHtmlCharacters(noteContent, { detectCodeBlock: true }))
|
||||
|
||||
const files = [this.GetCodeThemeLink(codeBlockTheme), ...CSS_FILES]
|
||||
const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(noteContent, this.props.storagePath)
|
||||
|
||||
files.forEach((file) => {
|
||||
file = file.replace('file://', '')
|
||||
if (global.process.platform === 'win32') {
|
||||
file = file.replace('file:///', '')
|
||||
} else {
|
||||
file = file.replace('file://', '')
|
||||
}
|
||||
|
||||
exportTasks.push({
|
||||
src: file,
|
||||
dst: 'css'
|
||||
@@ -295,6 +334,21 @@ export default class MarkdownPreview extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
getScrollBarStyle () {
|
||||
const {
|
||||
theme
|
||||
} = this.props
|
||||
|
||||
switch (theme) {
|
||||
case 'dark':
|
||||
case 'solarized-dark':
|
||||
case 'monokai':
|
||||
return scrollBarDarkStyle
|
||||
default:
|
||||
return scrollBarStyle
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this.refs.root.setAttribute('sandbox', 'allow-scripts')
|
||||
this.refs.root.contentWindow.document.body.addEventListener('contextmenu', this.contextMenuHandler)
|
||||
@@ -303,6 +357,9 @@ export default class MarkdownPreview extends React.Component {
|
||||
<style id='style'></style>
|
||||
<link rel="stylesheet" id="codeTheme">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<style>
|
||||
${this.getScrollBarStyle()}
|
||||
</style>
|
||||
`
|
||||
|
||||
CSS_FILES.forEach((file) => {
|
||||
@@ -405,15 +462,8 @@ export default class MarkdownPreview extends React.Component {
|
||||
let { value, 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))
|
||||
})
|
||||
}
|
||||
let renderedHTML = this.markdown.render(value)
|
||||
attachmentManagement.migrateAttachments(renderedHTML, storagePath, noteKey)
|
||||
const renderedHTML = this.markdown.render(value)
|
||||
attachmentManagement.migrateAttachments(value, storagePath, noteKey)
|
||||
this.refs.root.contentWindow.document.body.innerHTML = attachmentManagement.fixLocalURLS(renderedHTML, storagePath)
|
||||
|
||||
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('input[type="checkbox"]'), (el) => {
|
||||
@@ -496,6 +546,30 @@ export default class MarkdownPreview extends React.Component {
|
||||
el.innerHTML = 'Sequence diagram parse error: ' + e.message
|
||||
}
|
||||
})
|
||||
|
||||
_.forEach(
|
||||
this.refs.root.contentWindow.document.querySelectorAll('.chart'),
|
||||
(el) => {
|
||||
try {
|
||||
const chartConfig = JSON.parse(el.innerHTML)
|
||||
el.innerHTML = ''
|
||||
var canvas = document.createElement('canvas')
|
||||
el.appendChild(canvas)
|
||||
/* eslint-disable no-new */
|
||||
new Chart(canvas, chartConfig)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
el.className = 'chart-error'
|
||||
el.innerHTML = 'chartjs diagram parse error: ' + e.message
|
||||
}
|
||||
}
|
||||
)
|
||||
_.forEach(
|
||||
this.refs.root.contentWindow.document.querySelectorAll('.mermaid'),
|
||||
(el) => {
|
||||
mermaidRender(el, htmlTextHelper.decodeEntities(el.innerHTML), theme)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
focus () {
|
||||
|
||||
@@ -68,7 +68,7 @@ body
|
||||
padding 5px
|
||||
margin -5px
|
||||
border-radius 5px
|
||||
.flowchart-error, .sequence-error
|
||||
.flowchart-error, .sequence-error .chart-error
|
||||
background-color errorBackgroundColor
|
||||
color errorTextColor
|
||||
padding 5px
|
||||
@@ -213,7 +213,7 @@ pre
|
||||
margin 0 0 1em
|
||||
display flex
|
||||
line-height 1.4em
|
||||
&.flowchart, &.sequence
|
||||
&.flowchart, &.sequence, &.chart
|
||||
display flex
|
||||
justify-content center
|
||||
background-color white
|
||||
|
||||
39
browser/components/render/MermaidRender.js
Normal file
39
browser/components/render/MermaidRender.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import mermaidAPI from 'mermaid'
|
||||
|
||||
// fixes bad styling in the mermaid dark theme
|
||||
const darkThemeStyling = `
|
||||
.loopText tspan {
|
||||
fill: white;
|
||||
}`
|
||||
|
||||
function getRandomInt (min, max) {
|
||||
return Math.floor(Math.random() * (max - min)) + min
|
||||
}
|
||||
|
||||
function getId () {
|
||||
var pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
||||
var id = 'm-'
|
||||
for (var i = 0; i < 7; i++) {
|
||||
id += pool[getRandomInt(0, 16)]
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
function render (element, content, theme) {
|
||||
try {
|
||||
let isDarkTheme = theme === 'dark' || theme === 'solarized-dark' || theme === 'monokai'
|
||||
mermaidAPI.initialize({
|
||||
theme: isDarkTheme ? 'dark' : 'default',
|
||||
themeCSS: isDarkTheme ? darkThemeStyling : ''
|
||||
})
|
||||
mermaidAPI.render(getId(), content, (svgGraph) => {
|
||||
element.innerHTML = svgGraph
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
element.className = 'mermaid-error'
|
||||
element.innerHTML = 'mermaid diagram parse error: ' + e.message
|
||||
}
|
||||
}
|
||||
|
||||
export default render
|
||||
53
browser/lib/TextEditorInterface.js
Normal file
53
browser/lib/TextEditorInterface.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import { Point } from '@susisu/mte-kernel'
|
||||
|
||||
export default class TextEditorInterface {
|
||||
constructor (editor) {
|
||||
this.editor = editor
|
||||
}
|
||||
|
||||
getCursorPosition () {
|
||||
const pos = this.editor.getCursor()
|
||||
return new Point(pos.line, pos.ch)
|
||||
}
|
||||
|
||||
setCursorPosition (pos) {
|
||||
this.editor.setCursor({line: pos.row, ch: pos.column})
|
||||
}
|
||||
|
||||
setSelectionRange (range) {
|
||||
this.editor.setSelection({
|
||||
anchor: {line: range.start.row, ch: range.start.column},
|
||||
head: {line: range.end.row, ch: range.end.column}
|
||||
})
|
||||
}
|
||||
|
||||
getLastRow () {
|
||||
return this.editor.lastLine()
|
||||
}
|
||||
|
||||
acceptsTableEdit (row) {
|
||||
return true
|
||||
}
|
||||
|
||||
getLine (row) {
|
||||
return this.editor.getLine(row)
|
||||
}
|
||||
|
||||
insertLine (row, line) {
|
||||
this.editor.replaceRange(line, {line: row, ch: 0})
|
||||
}
|
||||
|
||||
deleteLine (row) {
|
||||
this.editor.replaceRange('', {line: row, ch: 0}, {line: row, ch: this.editor.getLine(row).length})
|
||||
}
|
||||
|
||||
replaceLines (startRow, endRow, lines) {
|
||||
endRow-- // because endRow is a first line after a table.
|
||||
const endRowCh = this.editor.getLine(endRow).length
|
||||
this.editor.replaceRange(lines, {line: startRow, ch: 0}, {line: endRow, ch: endRowCh})
|
||||
}
|
||||
|
||||
transact (func) {
|
||||
func()
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
import sanitizeHtml from 'sanitize-html'
|
||||
import { escapeHtmlCharacters } from './utils'
|
||||
|
||||
module.exports = function sanitizePlugin (md, options) {
|
||||
options = options || {}
|
||||
@@ -8,13 +9,26 @@ module.exports = function sanitizePlugin (md, options) {
|
||||
md.core.ruler.after('linkify', 'sanitize_inline', state => {
|
||||
for (let tokenIdx = 0; tokenIdx < state.tokens.length; tokenIdx++) {
|
||||
if (state.tokens[tokenIdx].type === 'html_block') {
|
||||
state.tokens[tokenIdx].content = sanitizeHtml(state.tokens[tokenIdx].content, options)
|
||||
state.tokens[tokenIdx].content = sanitizeHtml(
|
||||
state.tokens[tokenIdx].content,
|
||||
options
|
||||
)
|
||||
}
|
||||
if (state.tokens[tokenIdx].type === 'fence') {
|
||||
// escapeHtmlCharacters has better performance
|
||||
state.tokens[tokenIdx].content = escapeHtmlCharacters(
|
||||
state.tokens[tokenIdx].content,
|
||||
{ skipSingleQuote: true }
|
||||
)
|
||||
}
|
||||
if (state.tokens[tokenIdx].type === 'inline') {
|
||||
const inlineTokens = state.tokens[tokenIdx].children
|
||||
for (let childIdx = 0; childIdx < inlineTokens.length; childIdx++) {
|
||||
if (inlineTokens[childIdx].type === 'html_inline') {
|
||||
inlineTokens[childIdx].content = sanitizeHtml(inlineTokens[childIdx].content, options)
|
||||
inlineTokens[childIdx].content = sanitizeHtml(
|
||||
inlineTokens[childIdx].content,
|
||||
options
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,12 @@ class Markdown {
|
||||
if (langType === 'sequence') {
|
||||
return `<pre class="sequence">${str}</pre>`
|
||||
}
|
||||
if (langType === 'chart') {
|
||||
return `<pre class="chart">${str}</pre>`
|
||||
}
|
||||
if (langType === 'mermaid') {
|
||||
return `<pre class="mermaid">${str}</pre>`
|
||||
}
|
||||
return '<pre class="code CodeMirror">' +
|
||||
'<span class="filename">' + fileName + '</span>' +
|
||||
createGutter(str, firstLineNumber) +
|
||||
@@ -157,6 +163,22 @@ class Markdown {
|
||||
}
|
||||
})
|
||||
|
||||
// Ditaa support
|
||||
this.md.use(require('markdown-it-plantuml'), {
|
||||
openMarker: '@startditaa',
|
||||
closeMarker: '@endditaa',
|
||||
generateSource: function (umlCode) {
|
||||
const stripTrailingSlash = (url) => url.endsWith('/') ? url.slice(0, -1) : url
|
||||
// Currently PlantUML server doesn't support Ditaa in SVG, so we set the format as PNG at the moment.
|
||||
const serverAddress = stripTrailingSlash(config.preview.plantUMLServerAddress) + '/png'
|
||||
const s = unescape(encodeURIComponent(umlCode))
|
||||
const zippedCode = deflate.encode64(
|
||||
deflate.zip_deflate(`@startditaa\n${s}\n@endditaa`, 9)
|
||||
)
|
||||
return `${serverAddress}/${zippedCode}`
|
||||
}
|
||||
})
|
||||
|
||||
// Override task item
|
||||
this.md.block.ruler.at('paragraph', function (state, startLine/*, endLine */) {
|
||||
let content, terminate, i, l, token
|
||||
@@ -245,4 +267,3 @@ class Markdown {
|
||||
}
|
||||
|
||||
export default Markdown
|
||||
|
||||
|
||||
@@ -23,7 +23,9 @@ function findByWordOrTag (notes, block) {
|
||||
return true
|
||||
}
|
||||
if (note.type === 'SNIPPET_NOTE') {
|
||||
return note.description.match(wordRegExp)
|
||||
return note.description.match(wordRegExp) || note.snippets.some((snippet) => {
|
||||
return snippet.name.match(wordRegExp) || snippet.content.match(wordRegExp)
|
||||
})
|
||||
} else if (note.type === 'MARKDOWN_NOTE') {
|
||||
return note.content.match(wordRegExp)
|
||||
}
|
||||
|
||||
@@ -6,52 +6,113 @@ export function lastFindInArray (array, callback) {
|
||||
}
|
||||
}
|
||||
|
||||
export function escapeHtmlCharacters (text) {
|
||||
const matchHtmlRegExp = /["'&<>]/
|
||||
const str = '' + text
|
||||
const match = matchHtmlRegExp.exec(str)
|
||||
export function escapeHtmlCharacters (
|
||||
html,
|
||||
opt = { detectCodeBlock: false, skipSingleQuote: false }
|
||||
) {
|
||||
const matchHtmlRegExp = /["'&<>]/g
|
||||
const matchCodeBlockRegExp = /```/g
|
||||
const escapes = ['"', '&', ''', '<', '>']
|
||||
let match = null
|
||||
const replaceAt = (str, index, replace) =>
|
||||
str.substr(0, index) +
|
||||
replace +
|
||||
str.substr(index + replace.length - (replace.length - 1))
|
||||
|
||||
if (!match) {
|
||||
return str
|
||||
}
|
||||
|
||||
let escape
|
||||
let html = ''
|
||||
let index = 0
|
||||
let lastIndex = 0
|
||||
|
||||
for (index = match.index; index < str.length; index++) {
|
||||
switch (str.charCodeAt(index)) {
|
||||
case 34: // "
|
||||
escape = '"'
|
||||
break
|
||||
case 38: // &
|
||||
escape = '&'
|
||||
break
|
||||
case 39: // '
|
||||
escape = '''
|
||||
break
|
||||
case 60: // <
|
||||
escape = '<'
|
||||
break
|
||||
case 62: // >
|
||||
escape = '>'
|
||||
break
|
||||
default:
|
||||
while ((match = matchHtmlRegExp.exec(html)) !== null) {
|
||||
const current = { char: match[0], index: match.index }
|
||||
const codeBlockIndexs = []
|
||||
let openCodeBlock = null
|
||||
// if the detectCodeBlock option is activated then this function should skip
|
||||
// characters that needed to be escape but located in code block
|
||||
if (opt.detectCodeBlock) {
|
||||
// The first type of code block is lines that start with 4 spaces
|
||||
// Here we check for the \n character located before the character that
|
||||
// needed to be escape. It means we check for the begining of the line that
|
||||
// contain that character, then we check if there are 4 spaces next to the
|
||||
// \n character (the line start with 4 spaces)
|
||||
let previousLineEnd = current.index - 1
|
||||
while (html[previousLineEnd] !== '\n' && previousLineEnd !== -1) {
|
||||
previousLineEnd--
|
||||
}
|
||||
// 4 spaces means this character is in a code block
|
||||
if (
|
||||
html[previousLineEnd + 1] === ' ' &&
|
||||
html[previousLineEnd + 2] === ' ' &&
|
||||
html[previousLineEnd + 3] === ' ' &&
|
||||
html[previousLineEnd + 4] === ' '
|
||||
) {
|
||||
// skip the current character
|
||||
continue
|
||||
}
|
||||
// The second type of code block is lines that wrapped in ```
|
||||
// We will get the position of each ```
|
||||
// then push it into an array
|
||||
// then the array returned will be like this:
|
||||
// [startCodeblock, endCodeBlock, startCodeBlock, endCodeBlock]
|
||||
while ((openCodeBlock = matchCodeBlockRegExp.exec(html)) !== null) {
|
||||
codeBlockIndexs.push(openCodeBlock.index)
|
||||
}
|
||||
let shouldSkipChar = false
|
||||
// we loop through the array of positions
|
||||
// we skip 2 element as the i index position is the position of ``` that
|
||||
// open the codeblock and the i + 1 is the position of the ``` that close
|
||||
// the code block
|
||||
for (let i = 0; i < codeBlockIndexs.length; i += 2) {
|
||||
// the i index position is the position of the ``` that open code block
|
||||
// so we have to + 2 as that position is the position of the first ` in the ````
|
||||
// but we need to make sure that the position current character is larger
|
||||
// that the last ` in the ``` that open the code block so we have to take
|
||||
// the position of the first ` and + 2
|
||||
// the i + 1 index position is the closing ``` so the char must less than it
|
||||
if (
|
||||
current.index > codeBlockIndexs[i] + 2 &&
|
||||
current.index < codeBlockIndexs[i + 1]
|
||||
) {
|
||||
// skip it
|
||||
shouldSkipChar = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (shouldSkipChar) {
|
||||
// skip the current character
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if (lastIndex !== index) {
|
||||
html += str.substring(lastIndex, index)
|
||||
// otherwise, escape it !!!
|
||||
if (current.char === '&') {
|
||||
// when escaping character & we have to be becareful as the & could be a part
|
||||
// of an escaped character like " will be came &quot;
|
||||
let nextStr = ''
|
||||
let nextIndex = current.index
|
||||
let escapedStr = false
|
||||
// maximum length of an escaped string is 5. For example ('"')
|
||||
// we take the next 5 character of the next string if it is one of the string:
|
||||
// ['"', '&', ''', '<', '>'] then we will not escape the & character
|
||||
// as it is a part of the escaped string and should not be escaped
|
||||
while (nextStr.length <= 5) {
|
||||
nextStr += html[nextIndex]
|
||||
nextIndex++
|
||||
if (escapes.indexOf(nextStr) !== -1) {
|
||||
escapedStr = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!escapedStr) {
|
||||
// this & char is not a part of an escaped string
|
||||
html = replaceAt(html, current.index, '&')
|
||||
}
|
||||
} else if (current.char === '"') {
|
||||
html = replaceAt(html, current.index, '"')
|
||||
} else if (current.char === "'" && !opt.skipSingleQuote) {
|
||||
html = replaceAt(html, current.index, ''')
|
||||
} else if (current.char === '<') {
|
||||
html = replaceAt(html, current.index, '<')
|
||||
} else if (current.char === '>') {
|
||||
html = replaceAt(html, current.index, '>')
|
||||
}
|
||||
|
||||
lastIndex = index + 1
|
||||
html += escape
|
||||
}
|
||||
|
||||
return lastIndex !== index
|
||||
? html + str.substring(lastIndex, index)
|
||||
: html
|
||||
return html
|
||||
}
|
||||
|
||||
export function isObjectEqual (a, b) {
|
||||
|
||||
@@ -4,12 +4,14 @@ import CSSModules from 'browser/lib/CSSModules'
|
||||
import styles from './FullscreenButton.styl'
|
||||
import i18n from 'browser/lib/i18n'
|
||||
|
||||
const OSX = global.process.platform === 'darwin'
|
||||
const hotkey = (OSX ? i18n.__('Command(⌘)') : i18n.__('Ctrl(^)')) + '+B'
|
||||
const FullscreenButton = ({
|
||||
onClick
|
||||
}) => (
|
||||
<button styleName='control-fullScreenButton' title={i18n.__('Fullscreen')} onMouseDown={(e) => onClick(e)}>
|
||||
<img styleName='iconInfo' src='../resources/icon/icon-full.svg' />
|
||||
<span styleName='tooltip'>{i18n.__('Fullscreen')}</span>
|
||||
<span styleName='tooltip'>{i18n.__('Fullscreen')}({hotkey})</span>
|
||||
</button>
|
||||
)
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
.control-infoButton-panel-trash
|
||||
z-index 200
|
||||
margin-top 0px
|
||||
top 50px
|
||||
right 0px
|
||||
position absolute
|
||||
padding 20px 25px 0 25px
|
||||
|
||||
@@ -441,7 +441,7 @@ class SnippetNoteDetail extends React.Component {
|
||||
const isSuper = global.process.platform === 'darwin'
|
||||
? e.metaKey
|
||||
: e.ctrlKey
|
||||
if (isSuper) {
|
||||
if (isSuper && !e.shiftKey) {
|
||||
e.preventDefault()
|
||||
this.addSnippet()
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import styles from './TagSelect.styl'
|
||||
import _ from 'lodash'
|
||||
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||
import i18n from 'browser/lib/i18n'
|
||||
import ee from 'browser/main/lib/eventEmitter'
|
||||
|
||||
class TagSelect extends React.Component {
|
||||
constructor (props) {
|
||||
@@ -13,16 +14,26 @@ class TagSelect extends React.Component {
|
||||
this.state = {
|
||||
newTag: ''
|
||||
}
|
||||
this.addtagHandler = this.handleAddTag.bind(this)
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this.value = this.props.value
|
||||
ee.on('editor:add-tag', this.addtagHandler)
|
||||
}
|
||||
|
||||
componentDidUpdate () {
|
||||
this.value = this.props.value
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
ee.off('editor:add-tag', this.addtagHandler)
|
||||
}
|
||||
|
||||
handleAddTag () {
|
||||
this.refs.newTag.focus()
|
||||
}
|
||||
|
||||
handleNewTagInputKeyDown (e) {
|
||||
switch (e.keyCode) {
|
||||
case 9:
|
||||
|
||||
@@ -9,6 +9,7 @@ import ee from 'browser/main/lib/eventEmitter'
|
||||
import StatusBar from '../StatusBar'
|
||||
import i18n from 'browser/lib/i18n'
|
||||
import debounceRender from 'react-debounce-render'
|
||||
import searchFromNotes from 'browser/lib/search'
|
||||
|
||||
const OSX = global.process.platform === 'darwin'
|
||||
|
||||
@@ -35,11 +36,38 @@ class Detail extends React.Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { location, data, config } = this.props
|
||||
const { location, data, params, config } = this.props
|
||||
let note = null
|
||||
|
||||
if (location.query.key != null) {
|
||||
const noteKey = location.query.key
|
||||
note = data.noteMap.get(noteKey)
|
||||
const allNotes = data.noteMap.map(note => note)
|
||||
const trashedNotes = data.trashedSet.toJS().map(uniqueKey => data.noteMap.get(uniqueKey))
|
||||
let displayedNotes = allNotes
|
||||
|
||||
if (location.pathname.match(/\/searched/)) {
|
||||
const searchStr = params.searchword
|
||||
displayedNotes = searchStr === undefined || searchStr === '' ? allNotes
|
||||
: searchFromNotes(allNotes, searchStr)
|
||||
}
|
||||
|
||||
if (location.pathname.match(/\/tags/)) {
|
||||
const listOfTags = params.tagname.split(' ')
|
||||
displayedNotes = data.noteMap.map(note => note).filter(note =>
|
||||
listOfTags.every(tag => note.tags.includes(tag))
|
||||
)
|
||||
}
|
||||
|
||||
if (location.pathname.match(/\/trashed/)) {
|
||||
displayedNotes = trashedNotes
|
||||
} else {
|
||||
displayedNotes = _.differenceWith(displayedNotes, trashedNotes, (note, trashed) => note.key === trashed.key)
|
||||
}
|
||||
|
||||
const noteKeys = displayedNotes.map(note => note.key)
|
||||
if (noteKeys.includes(noteKey)) {
|
||||
note = data.noteMap.get(noteKey)
|
||||
}
|
||||
}
|
||||
|
||||
if (note == null) {
|
||||
|
||||
@@ -156,8 +156,7 @@ class TopBar extends React.Component {
|
||||
if (this.state.isSearching) {
|
||||
el.blur()
|
||||
} else {
|
||||
el.focus()
|
||||
el.setSelectionRange(0, el.value.length)
|
||||
el.select()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,12 @@ body
|
||||
font-weight 200
|
||||
-webkit-font-smoothing antialiased
|
||||
|
||||
::-webkit-scrollbar
|
||||
width 12px
|
||||
|
||||
::-webkit-scrollbar-thumb
|
||||
background-color rgba(0, 0, 0, 0.15)
|
||||
|
||||
button, input, select, textarea
|
||||
font-family DEFAULT_FONTS
|
||||
|
||||
@@ -85,9 +91,11 @@ modalBackColor = white
|
||||
absolute top left bottom right
|
||||
background-color modalBackColor
|
||||
z-index modalZIndex + 1
|
||||
|
||||
|
||||
|
||||
body[data-theme="dark"]
|
||||
::-webkit-scrollbar-thumb
|
||||
background-color rgba(0, 0, 0, 0.3)
|
||||
.ModalBase
|
||||
.modalBack
|
||||
background-color $ui-dark-backgroundColor
|
||||
@@ -128,6 +136,8 @@ body[data-theme="dark"]
|
||||
z-index modalZIndex + 5
|
||||
|
||||
body[data-theme="solarized-dark"]
|
||||
::-webkit-scrollbar-thumb
|
||||
background-color rgba(0, 0, 0, 0.3)
|
||||
.ModalBase
|
||||
.modalBack
|
||||
background-color $ui-solarized-dark-backgroundColor
|
||||
@@ -135,9 +145,10 @@ body[data-theme="solarized-dark"]
|
||||
color: $ui-solarized-dark-text-color
|
||||
|
||||
body[data-theme="monokai"]
|
||||
::-webkit-scrollbar-thumb
|
||||
background-color rgba(0, 0, 0, 0.3)
|
||||
.ModalBase
|
||||
.modalBack
|
||||
background-color $ui-monokai-backgroundColor
|
||||
.sortableItemHelper
|
||||
color: $ui-monokai-text-color
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import i18n from 'browser/lib/i18n'
|
||||
|
||||
const STORAGE_FOLDER_PLACEHOLDER = ':storage'
|
||||
const DESTINATION_FOLDER = 'attachments'
|
||||
const PATH_SEPARATORS = escapeStringRegexp(path.posix.sep) + escapeStringRegexp(path.win32.sep)
|
||||
|
||||
/**
|
||||
* @description
|
||||
@@ -76,14 +77,14 @@ function createAttachmentDestinationFolder (destinationStoragePath, noteKey) {
|
||||
|
||||
/**
|
||||
* @description Moves attachments from the old location ('/images') to the new one ('/attachments/noteKey)
|
||||
* @param renderedHTML HTML of the current note
|
||||
* @param markdownContent of the current note
|
||||
* @param storagePath Storage path of the current note
|
||||
* @param noteKey Key of the current note
|
||||
*/
|
||||
function migrateAttachments (renderedHTML, storagePath, noteKey) {
|
||||
if (sander.existsSync(path.join(storagePath, 'images'))) {
|
||||
const attachments = getAttachmentsInContent(renderedHTML) || []
|
||||
if (attachments !== []) {
|
||||
function migrateAttachments (markdownContent, storagePath, noteKey) {
|
||||
if (noteKey !== undefined && sander.existsSync(path.join(storagePath, 'images'))) {
|
||||
const attachments = getAttachmentsInMarkdownContent(markdownContent) || []
|
||||
if (attachments.length) {
|
||||
createAttachmentDestinationFolder(storagePath, noteKey)
|
||||
}
|
||||
for (const attachment of attachments) {
|
||||
@@ -106,7 +107,10 @@ function migrateAttachments (renderedHTML, storagePath, noteKey) {
|
||||
* @returns {String} postprocessed HTML in which all :storage references are mapped to the actual paths.
|
||||
*/
|
||||
function fixLocalURLS (renderedHTML, storagePath) {
|
||||
return renderedHTML.replace(new RegExp(mdurl.encode(path.sep), 'g'), path.sep).replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER, 'g'), 'file:///' + path.join(storagePath, DESTINATION_FOLDER))
|
||||
return renderedHTML.replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '.*?"', 'g'), function (match) {
|
||||
var encodedPathSeparators = new RegExp(mdurl.encode(path.win32.sep) + '|' + mdurl.encode(path.posix.sep), 'g')
|
||||
return match.replace(encodedPathSeparators, path.sep).replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER, 'g'), 'file:///' + path.join(storagePath, DESTINATION_FOLDER))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,13 +190,13 @@ function handlePastImageEvent (codeEditor, storageKey, noteKey, dataTransferItem
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns all attachment paths of the given markdown
|
||||
* @param {String} markdownContent content in which the attachment paths should be found
|
||||
* @returns {String[]} Array of the relative paths (starting with :storage) of the attachments of the given markdown
|
||||
*/
|
||||
function getAttachmentsInContent (markdownContent) {
|
||||
const preparedInput = markdownContent.replace(new RegExp(mdurl.encode(path.sep), 'g'), path.sep)
|
||||
const regexp = new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '(' + escapeStringRegexp(path.sep) + '|/)' + '?([a-zA-Z0-9]|-)*' + '(' + escapeStringRegexp(path.sep) + '|/)' + '([a-zA-Z0-9]|\\.)+(\\.[a-zA-Z0-9]+)?', 'g')
|
||||
* @description Returns all attachment paths of the given markdown
|
||||
* @param {String} markdownContent content in which the attachment paths should be found
|
||||
* @returns {String[]} Array of the relative paths (starting with :storage) of the attachments of the given markdown
|
||||
*/
|
||||
function getAttachmentsInMarkdownContent (markdownContent) {
|
||||
const preparedInput = markdownContent.replace(new RegExp('[' + PATH_SEPARATORS + ']', 'g'), path.sep)
|
||||
const regexp = new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '(' + escapeStringRegexp(path.sep) + ')' + '?([a-zA-Z0-9]|-)*' + '(' + escapeStringRegexp(path.sep) + ')' + '([a-zA-Z0-9]|\\.)+(\\.[a-zA-Z0-9]+)?', 'g')
|
||||
return preparedInput.match(regexp)
|
||||
}
|
||||
|
||||
@@ -203,7 +207,7 @@ function getAttachmentsInContent (markdownContent) {
|
||||
* @returns {String[]} Absolute paths of the referenced attachments
|
||||
*/
|
||||
function getAbsolutePathsOfAttachmentsInContent (markdownContent, storagePath) {
|
||||
const temp = getAttachmentsInContent(markdownContent) || []
|
||||
const temp = getAttachmentsInMarkdownContent(markdownContent) || []
|
||||
const result = []
|
||||
for (const relativePath of temp) {
|
||||
result.push(relativePath.replace(new RegExp(STORAGE_FOLDER_PLACEHOLDER, 'g'), path.join(storagePath, DESTINATION_FOLDER)))
|
||||
@@ -239,7 +243,8 @@ function moveAttachments (oldPath, newPath, noteKey, newNoteKey, noteContent) {
|
||||
*/
|
||||
function replaceNoteKeyWithNewNoteKey (noteContent, oldNoteKey, newNoteKey) {
|
||||
if (noteContent) {
|
||||
return noteContent.replace(new RegExp(STORAGE_FOLDER_PLACEHOLDER + escapeStringRegexp(path.sep) + oldNoteKey, 'g'), path.join(STORAGE_FOLDER_PLACEHOLDER, newNoteKey))
|
||||
const preparedInput = noteContent.replace(new RegExp('[' + PATH_SEPARATORS + ']', 'g'), path.sep)
|
||||
return preparedInput.replace(new RegExp(STORAGE_FOLDER_PLACEHOLDER + escapeStringRegexp(path.sep) + oldNoteKey, 'g'), path.join(STORAGE_FOLDER_PLACEHOLDER, newNoteKey))
|
||||
}
|
||||
return noteContent
|
||||
}
|
||||
@@ -277,7 +282,7 @@ function deleteAttachmentsNotPresentInNote (markdownContent, storageKey, noteKey
|
||||
}
|
||||
const targetStorage = findStorage.findStorage(storageKey)
|
||||
const attachmentFolder = path.join(targetStorage.path, DESTINATION_FOLDER, noteKey)
|
||||
const attachmentsInNote = getAttachmentsInContent(markdownContent)
|
||||
const attachmentsInNote = getAttachmentsInMarkdownContent(markdownContent)
|
||||
const attachmentsInNoteOnlyFileNames = []
|
||||
if (attachmentsInNote) {
|
||||
for (let i = 0; i < attachmentsInNote.length; i++) {
|
||||
@@ -348,7 +353,7 @@ function generateFileNotFoundMarkdown () {
|
||||
*/
|
||||
function isAttachmentLink (text) {
|
||||
if (text) {
|
||||
return text.match(new RegExp('.*\\[.*\\]\\( *' + escapeStringRegexp(STORAGE_FOLDER_PLACEHOLDER) + escapeStringRegexp(path.sep) + '.*\\).*', 'gi')) != null
|
||||
return text.match(new RegExp('.*\\[.*\\]\\( *' + escapeStringRegexp(STORAGE_FOLDER_PLACEHOLDER) + '[' + PATH_SEPARATORS + ']' + '.*\\).*', 'gi')) != null
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -364,7 +369,7 @@ function isAttachmentLink (text) {
|
||||
function handleAttachmentLinkPaste (storageKey, noteKey, linkText) {
|
||||
if (storageKey != null && noteKey != null && linkText != null) {
|
||||
const storagePath = findStorage.findStorage(storageKey).path
|
||||
const attachments = getAttachmentsInContent(linkText) || []
|
||||
const attachments = getAttachmentsInMarkdownContent(linkText) || []
|
||||
const replaceInstructions = []
|
||||
const copies = []
|
||||
for (const attachment of attachments) {
|
||||
@@ -373,13 +378,13 @@ function handleAttachmentLinkPaste (storageKey, noteKey, linkText) {
|
||||
sander.exists(absPathOfAttachment)
|
||||
.then((fileExists) => {
|
||||
if (!fileExists) {
|
||||
const fileNotFoundRegexp = new RegExp('!?' + escapeStringRegexp('[') + '[\\w|\\d|\\s|\\.]*\\]\\(\\s*' + STORAGE_FOLDER_PLACEHOLDER + '[\\w|\\d|\\-|' + escapeStringRegexp(path.sep) + ']*' + escapeStringRegexp(path.basename(absPathOfAttachment)) + escapeStringRegexp(')'))
|
||||
const fileNotFoundRegexp = new RegExp('!?' + escapeStringRegexp('[') + '[\\w|\\d|\\s|\\.]*\\]\\(\\s*' + STORAGE_FOLDER_PLACEHOLDER + '[\\w|\\d|\\-|' + PATH_SEPARATORS + ']*' + escapeStringRegexp(path.basename(absPathOfAttachment)) + escapeStringRegexp(')'))
|
||||
replaceInstructions.push({regexp: fileNotFoundRegexp, replacement: this.generateFileNotFoundMarkdown()})
|
||||
return Promise.resolve()
|
||||
}
|
||||
return this.copyAttachment(absPathOfAttachment, storageKey, noteKey)
|
||||
.then((fileName) => {
|
||||
const replaceLinkRegExp = new RegExp(escapeStringRegexp('(') + ' *' + STORAGE_FOLDER_PLACEHOLDER + '[\\w|\\d|\\-|' + escapeStringRegexp(path.sep) + ']*' + escapeStringRegexp(path.basename(absPathOfAttachment)) + ' *' + escapeStringRegexp(')'))
|
||||
const replaceLinkRegExp = new RegExp(escapeStringRegexp('(') + ' *' + STORAGE_FOLDER_PLACEHOLDER + '[\\w|\\d|\\-|' + PATH_SEPARATORS + ']*' + escapeStringRegexp(path.basename(absPathOfAttachment)) + ' *' + escapeStringRegexp(')'))
|
||||
replaceInstructions.push({
|
||||
regexp: replaceLinkRegExp,
|
||||
replacement: '(' + path.join(STORAGE_FOLDER_PLACEHOLDER, noteKey, fileName) + ')'
|
||||
@@ -408,7 +413,7 @@ module.exports = {
|
||||
generateAttachmentMarkdown,
|
||||
handleAttachmentDrop,
|
||||
handlePastImageEvent,
|
||||
getAttachmentsInContent,
|
||||
getAttachmentsInMarkdownContent,
|
||||
getAbsolutePathsOfAttachmentsInContent,
|
||||
removeStorageAndNoteReferences,
|
||||
deleteAttachmentFolder,
|
||||
|
||||
@@ -12,8 +12,7 @@ class NewNoteModal extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
}
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
@@ -35,19 +34,20 @@ class NewNoteModal extends React.Component {
|
||||
title: '',
|
||||
content: ''
|
||||
})
|
||||
.then((note) => {
|
||||
.then(note => {
|
||||
const noteHash = note.key
|
||||
dispatch({
|
||||
type: 'UPDATE_NOTE',
|
||||
note: note
|
||||
})
|
||||
|
||||
hashHistory.push({
|
||||
pathname: location.pathname,
|
||||
query: {key: noteHash}
|
||||
query: { key: noteHash }
|
||||
})
|
||||
ee.emit('list:jump', noteHash)
|
||||
ee.emit('detail:focus')
|
||||
this.props.close()
|
||||
setTimeout(this.props.close, 200)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -69,13 +69,15 @@ class NewNoteModal extends React.Component {
|
||||
folder: folder,
|
||||
title: '',
|
||||
description: '',
|
||||
snippets: [{
|
||||
name: '',
|
||||
mode: 'text',
|
||||
content: ''
|
||||
}]
|
||||
snippets: [
|
||||
{
|
||||
name: '',
|
||||
mode: 'text',
|
||||
content: ''
|
||||
}
|
||||
]
|
||||
})
|
||||
.then((note) => {
|
||||
.then(note => {
|
||||
const noteHash = note.key
|
||||
dispatch({
|
||||
type: 'UPDATE_NOTE',
|
||||
@@ -83,11 +85,11 @@ class NewNoteModal extends React.Component {
|
||||
})
|
||||
hashHistory.push({
|
||||
pathname: location.pathname,
|
||||
query: {key: noteHash}
|
||||
query: { key: noteHash }
|
||||
})
|
||||
ee.emit('list:jump', noteHash)
|
||||
ee.emit('detail:focus')
|
||||
this.props.close()
|
||||
setTimeout(this.props.close, 200)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -106,49 +108,65 @@ class NewNoteModal extends React.Component {
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div styleName='root'
|
||||
<div
|
||||
styleName='root'
|
||||
tabIndex='-1'
|
||||
onKeyDown={(e) => this.handleKeyDown(e)}
|
||||
onKeyDown={e => this.handleKeyDown(e)}
|
||||
>
|
||||
<div styleName='header'>
|
||||
<div styleName='title'>{i18n.__('Make a note')}</div>
|
||||
</div>
|
||||
<ModalEscButton handleEscButtonClick={(e) => this.handleCloseButtonClick(e)} />
|
||||
<ModalEscButton
|
||||
handleEscButtonClick={e => this.handleCloseButtonClick(e)}
|
||||
/>
|
||||
<div styleName='control'>
|
||||
<button styleName='control-button'
|
||||
onClick={(e) => this.handleMarkdownNoteButtonClick(e)}
|
||||
onKeyDown={(e) => this.handleMarkdownNoteButtonKeyDown(e)}
|
||||
<button
|
||||
styleName='control-button'
|
||||
onClick={e => this.handleMarkdownNoteButtonClick(e)}
|
||||
onKeyDown={e => this.handleMarkdownNoteButtonKeyDown(e)}
|
||||
ref='markdownButton'
|
||||
>
|
||||
<i styleName='control-button-icon'
|
||||
className='fa fa-file-text-o'
|
||||
/><br />
|
||||
<span styleName='control-button-label'>{i18n.__('Markdown Note')}</span><br />
|
||||
<span styleName='control-button-description'>{i18n.__('This format is for creating text documents. Checklists, code blocks and Latex blocks are available.')}</span>
|
||||
<i styleName='control-button-icon' className='fa fa-file-text-o' />
|
||||
<br />
|
||||
<span styleName='control-button-label'>
|
||||
{i18n.__('Markdown Note')}
|
||||
</span>
|
||||
<br />
|
||||
<span styleName='control-button-description'>
|
||||
{i18n.__(
|
||||
'This format is for creating text documents. Checklists, code blocks and Latex blocks are available.'
|
||||
)}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<button styleName='control-button'
|
||||
onClick={(e) => this.handleSnippetNoteButtonClick(e)}
|
||||
onKeyDown={(e) => this.handleSnippetNoteButtonKeyDown(e)}
|
||||
<button
|
||||
styleName='control-button'
|
||||
onClick={e => this.handleSnippetNoteButtonClick(e)}
|
||||
onKeyDown={e => this.handleSnippetNoteButtonKeyDown(e)}
|
||||
ref='snippetButton'
|
||||
>
|
||||
<i styleName='control-button-icon'
|
||||
className='fa fa-code'
|
||||
/><br />
|
||||
<span styleName='control-button-label'>{i18n.__('Snippet Note')}</span><br />
|
||||
<span styleName='control-button-description'>{i18n.__('This format is for creating code snippets. Multiple snippets can be grouped into a single note.')}
|
||||
<i styleName='control-button-icon' className='fa fa-code' /><br />
|
||||
<span styleName='control-button-label'>
|
||||
{i18n.__('Snippet Note')}
|
||||
</span>
|
||||
<br />
|
||||
<span styleName='control-button-description'>
|
||||
{i18n.__(
|
||||
'This format is for creating code snippets. Multiple snippets can be grouped into a single note.'
|
||||
)}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
<div styleName='description'><i className='fa fa-arrows-h' />{i18n.__('Tab to switch format')}</div>
|
||||
<div styleName='description'>
|
||||
<i className='fa fa-arrows-h' />{i18n.__('Tab to switch format')}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
NewNoteModal.propTypes = {
|
||||
}
|
||||
NewNoteModal.propTypes = {}
|
||||
|
||||
export default CSSModules(NewNoteModal, styles)
|
||||
|
||||
@@ -27,7 +27,12 @@ class SnippetEditor extends React.Component {
|
||||
dragDrop: false,
|
||||
foldGutter: true,
|
||||
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
|
||||
autoCloseBrackets: true,
|
||||
autoCloseBrackets: {
|
||||
pairs: '()[]{}\'\'""$$**``',
|
||||
triples: '```"""\'\'\'',
|
||||
explode: '[]{}``$$',
|
||||
override: true
|
||||
},
|
||||
mode: 'null'
|
||||
})
|
||||
this.cm.setSize('100%', '100%')
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
# Build
|
||||
|
||||
## 環境
|
||||
* npm: 4.x
|
||||
* node: 7.x
|
||||
|
||||
`npm v5.x` だと `$ grunt pre-build` が失敗するので、 `npm v4.x` を使用してください。
|
||||
|
||||
## 開発
|
||||
|
||||
Webpack HRMを使います。
|
||||
次の命令から私達がしておいた設定を使うことができます。
|
||||
Boostnoteの最上位ディレクトリにて以下のコマンドを実行して、
|
||||
デフォルトの設定の開発環境を起動させます。
|
||||
|
||||
依存するパッケージをインストールします。
|
||||
|
||||
@@ -27,15 +34,15 @@ $ yarn run dev-start
|
||||
|
||||
> ### 注意
|
||||
> 時々、直接リフレッシュをする必要があります。
|
||||
> 1. コンポネントのコンストラクター関数を編集する場合
|
||||
> 2. 新しいCSSクラスを追加する場合(1.の理由と同じ: CSSクラス名はコンポネントごとに書きなおされまが、この作業はコンストラクターで行われます。)
|
||||
> 1. コンポーネントのコンストラクタ関数を編集する場合
|
||||
> 2. 新しいCSSクラスを追加する場合(1.の理由と同じ: CSSクラス名はコンポーネントごとに書きなおされますが、この作業はコンストラクタで行われます。)
|
||||
|
||||
## 配布
|
||||
|
||||
Gruntを使います。
|
||||
実際の配布は`grunt`で実行できます。しかし、これにはCodesignとAuthenticodeの仮定が含まれるので、使っては行けないです。
|
||||
実際の配布は`grunt`で実行できます。しかし、これにはCodesignとAuthenticodeを実行するタスクが含まれるので、使用しないでください。
|
||||
|
||||
それで、実行ファイルを作るスクリプトを用意しておきました。
|
||||
代わりに、実行ファイルを作るスクリプトを用意しておきました。
|
||||
|
||||
このビルドはnpm v5.3.0では動かないのでv5.2.0で動かす必要があります。
|
||||
|
||||
|
||||
@@ -136,6 +136,15 @@ const file = {
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Format Table',
|
||||
click () {
|
||||
mainWindow.webContents.send('code:format-table')
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Print',
|
||||
accelerator: 'CommandOrControl+P',
|
||||
@@ -209,6 +218,16 @@ const edit = {
|
||||
label: 'Select All',
|
||||
accelerator: 'Command+A',
|
||||
selector: 'selectAll:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Add Tag',
|
||||
accelerator: 'CommandOrControl+Shift+T',
|
||||
click () {
|
||||
mainWindow.webContents.send('editor:add-tag')
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -235,14 +254,14 @@ const view = {
|
||||
},
|
||||
{
|
||||
label: 'Next Note',
|
||||
accelerator: 'Control+J',
|
||||
accelerator: 'CommandOrControl+]',
|
||||
click () {
|
||||
mainWindow.webContents.send('list:next')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Previous Note',
|
||||
accelerator: 'Control+K',
|
||||
accelerator: 'CommandOrControl+[',
|
||||
click () {
|
||||
mainWindow.webContents.send('list:prior')
|
||||
}
|
||||
@@ -267,6 +286,19 @@ const view = {
|
||||
mainWindow.setFullScreen(!mainWindow.isFullScreen())
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Toggle Side Bar',
|
||||
accelerator: 'CommandOrControl+B',
|
||||
click () {
|
||||
mainWindow.webContents.send('editor:fullscreen')
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
role: 'zoomin',
|
||||
accelerator: macOS ? 'CommandOrControl+Plus' : 'Control+='
|
||||
|
||||
35
package-lock.json
generated
35
package-lock.json
generated
@@ -1,35 +0,0 @@
|
||||
{
|
||||
"name": "boost",
|
||||
"version": "0.10.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"i18n-2": {
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/i18n-2/-/i18n-2-0.7.2.tgz",
|
||||
"integrity": "sha512-Rdh6vfpNhL7q61cNf27x7QGULTi1TcGLVdFb5OJ6dOiJo+EkOTqEg0+3xgyeEMgYhopUBsh2IiSkFkjM+EhEmA==",
|
||||
"requires": {
|
||||
"debug": "3.1.0",
|
||||
"sprintf": "0.1.5"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"sprintf": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz",
|
||||
"integrity": "sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "boost",
|
||||
"productName": "Boostnote",
|
||||
"version": "0.11.7",
|
||||
"version": "0.11.8",
|
||||
"main": "index.js",
|
||||
"description": "Boostnote",
|
||||
"license": "GPL-3.0",
|
||||
@@ -51,8 +51,10 @@
|
||||
"dependencies": {
|
||||
"@rokt33r/markdown-it-math": "^4.0.1",
|
||||
"@rokt33r/season": "^5.3.0",
|
||||
"@susisu/mte-kernel": "^2.0.0",
|
||||
"aws-sdk": "^2.48.0",
|
||||
"aws-sdk-mobile-analytics": "^0.9.2",
|
||||
"chart.js": "^2.7.2",
|
||||
"codemirror": "^5.39.0",
|
||||
"codemirror-mode-elixir": "^1.1.1",
|
||||
"electron-config": "^0.2.1",
|
||||
@@ -71,7 +73,7 @@
|
||||
"lodash": "^4.11.1",
|
||||
"lodash-move": "^1.1.1",
|
||||
"markdown-it": "^6.0.1",
|
||||
"markdown-it-admonition": "https://github.com/johannbre/markdown-it-admonition.git",
|
||||
"markdown-it-admonition": "^1.0.4",
|
||||
"markdown-it-emoji": "^1.1.1",
|
||||
"markdown-it-footnote": "^3.0.0",
|
||||
"markdown-it-imsize": "^2.0.1",
|
||||
@@ -81,6 +83,7 @@
|
||||
"markdown-it-plantuml": "^1.1.0",
|
||||
"markdown-it-smartarrows": "^1.0.1",
|
||||
"mdurl": "^1.0.1",
|
||||
"mermaid": "^8.0.0-rc.8",
|
||||
"moment": "^2.10.3",
|
||||
"mousetrap": "^1.6.1",
|
||||
"mousetrap-global-bind": "^1.1.0",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:mega: We've launched [Boostnote Bounty Program](http://bit.ly/2I5Tpik).
|
||||
:mega: The Boostnote team launches [IssueHunt](https://issuehunt.io/) for sustainable open-source ecosystem.
|
||||
|
||||

|
||||
|
||||
@@ -19,8 +19,10 @@ Thank you to all the people who already contributed to Boostnote!
|
||||
<a href="https://github.com/BoostIO/Boostnote/graphs/contributors"><img src="https://opencollective.com/boostnoteio/contributors.svg?width=890" /></a>
|
||||
|
||||
## Supporting Boostnote
|
||||
Boostnote is an open source project. It's an independent project with its ongoing development made possible entirely thanks to the support by these awesome [backers](https://github.com/BoostIO/Boostnote/blob/master/Backers.md). If you'd like to join them, please consider:
|
||||
- [Become a backer or sponsor on Open Collective.](https://opencollective.com/boostnoteio)
|
||||
Boostnote is an open source project. It's an independent project with its ongoing development made possible entirely thanks to the support by these awesome backers.
|
||||
|
||||
Any issues on Boostnote can be funded by anyone and that money will be distributed to contributors and maintainers. If you'd like to join them, please consider:
|
||||
- [Become a backer on IssueHunt](https://issuehunt.io/repos/53266139).
|
||||
|
||||
## Community
|
||||
- [Facebook Group](https://www.facebook.com/groups/boostnote/)
|
||||
|
||||
@@ -169,6 +169,43 @@ it('should replace the all ":storage" path with the actual storage path', functi
|
||||
expect(actual).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
it('should replace the ":storage" path with the actual storage path when they have different path separators', function () {
|
||||
const storageFolder = systemUnderTest.DESTINATION_FOLDER
|
||||
const testInput =
|
||||
'<html>\n' +
|
||||
' <head>\n' +
|
||||
' //header\n' +
|
||||
' </head>\n' +
|
||||
' <body data-theme="default">\n' +
|
||||
' <h2 data-line="0" id="Headline">Headline</h2>\n' +
|
||||
' <p data-line="2">\n' +
|
||||
' <img src=":storage' + mdurl.encode(path.win32.sep) + '0.6r4zdgc22xp.png" alt="dummyImage.png" >\n' +
|
||||
' </p>\n' +
|
||||
' <p data-line="4">\n' +
|
||||
' <a href=":storage' + mdurl.encode(path.posix.sep) + '0.q2i4iw0fyx.pdf">dummyPDF.pdf</a>\n' +
|
||||
' </p>\n' +
|
||||
' </body>\n' +
|
||||
'</html>'
|
||||
const storagePath = '<<dummyStoragePath>>'
|
||||
const expectedOutput =
|
||||
'<html>\n' +
|
||||
' <head>\n' +
|
||||
' //header\n' +
|
||||
' </head>\n' +
|
||||
' <body data-theme="default">\n' +
|
||||
' <h2 data-line="0" id="Headline">Headline</h2>\n' +
|
||||
' <p data-line="2">\n' +
|
||||
' <img src="file:///' + storagePath + path.sep + storageFolder + path.sep + '0.6r4zdgc22xp.png" alt="dummyImage.png" >\n' +
|
||||
' </p>\n' +
|
||||
' <p data-line="4">\n' +
|
||||
' <a href="file:///' + storagePath + path.sep + storageFolder + path.sep + '0.q2i4iw0fyx.pdf">dummyPDF.pdf</a>\n' +
|
||||
' </p>\n' +
|
||||
' </body>\n' +
|
||||
'</html>'
|
||||
const actual = systemUnderTest.fixLocalURLS(testInput, storagePath)
|
||||
expect(actual).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
it('should test that generateAttachmentMarkdown works correct both with previews and without', function () {
|
||||
const fileName = 'fileName'
|
||||
const path = 'path'
|
||||
@@ -180,27 +217,35 @@ it('should test that generateAttachmentMarkdown works correct both with previews
|
||||
expect(actual).toEqual(expected)
|
||||
})
|
||||
|
||||
it('should test that getAttachmentsInContent finds all attachments', function () {
|
||||
const testInput =
|
||||
'<html>\n' +
|
||||
' <head>\n' +
|
||||
' //header\n' +
|
||||
' </head>\n' +
|
||||
' <body data-theme="default">\n' +
|
||||
' <h2 data-line="0" id="Headline">Headline</h2>\n' +
|
||||
' <p data-line="2">\n' +
|
||||
' <img src=":storage' + mdurl.encode(path.sep) + '9c9c4ba3-bc1e-441f-9866-c1e9a806e31c' + mdurl.encode(path.sep) + '0.6r4zdgc22xp.png" alt="dummyImage.png" >\n' +
|
||||
' </p>\n' +
|
||||
' <p data-line="4">\n' +
|
||||
' <a href=":storage' + mdurl.encode(path.sep) + '9c9c4ba3-bc1e-441f-9866-c1e9a806e31c' + mdurl.encode(path.sep) + '0.q2i4iw0fyx.pdf">dummyPDF.pdf</a>\n' +
|
||||
' </p>\n' +
|
||||
' <p data-line="6">\n' +
|
||||
' <img src=":storage' + mdurl.encode(path.sep) + '9c9c4ba3-bc1e-441f-9866-c1e9a806e31c' + mdurl.encode(path.sep) + 'd6c5ee92.jpg" alt="dummyImage2.jpg">\n' +
|
||||
' </p>\n' +
|
||||
' </body>\n' +
|
||||
'</html>'
|
||||
const actual = systemUnderTest.getAttachmentsInContent(testInput)
|
||||
const expected = [':storage' + path.sep + '9c9c4ba3-bc1e-441f-9866-c1e9a806e31c' + path.sep + '0.6r4zdgc22xp.png', ':storage' + path.sep + '9c9c4ba3-bc1e-441f-9866-c1e9a806e31c' + path.sep + '0.q2i4iw0fyx.pdf', ':storage' + path.sep + '9c9c4ba3-bc1e-441f-9866-c1e9a806e31c' + path.sep + 'd6c5ee92.jpg']
|
||||
it('should test that migrateAttachments work when they have different path separators', function () {
|
||||
sander.existsSync = jest.fn(() => true)
|
||||
const dummyStoragePath = 'dummyStoragePath'
|
||||
const imagesPath = path.join(dummyStoragePath, 'images')
|
||||
const attachmentsPath = path.join(dummyStoragePath, 'attachments')
|
||||
const noteKey = 'noteKey'
|
||||
const testInput = '"# Test\n' +
|
||||
'\n' +
|
||||
'\n' +
|
||||
'"'
|
||||
|
||||
systemUnderTest.migrateAttachments(testInput, dummyStoragePath, noteKey)
|
||||
|
||||
expect(sander.existsSync.mock.calls[0][0]).toBe(imagesPath)
|
||||
expect(sander.existsSync.mock.calls[1][0]).toBe(path.join(imagesPath, '0.3b88d0dc.png'))
|
||||
expect(sander.existsSync.mock.calls[2][0]).toBe(path.join(attachmentsPath, '0.3b88d0dc.png'))
|
||||
expect(sander.existsSync.mock.calls[3][0]).toBe(path.join(imagesPath, '0.2cb8875c.pdf'))
|
||||
expect(sander.existsSync.mock.calls[4][0]).toBe(path.join(attachmentsPath, '0.2cb8875c.pdf'))
|
||||
})
|
||||
|
||||
it('should test that getAttachmentsInMarkdownContent finds all attachments when they have different path separators', function () {
|
||||
const testInput = '"# Test\n' +
|
||||
'\n' +
|
||||
'\n' +
|
||||
'\n' +
|
||||
'"'
|
||||
|
||||
const actual = systemUnderTest.getAttachmentsInMarkdownContent(testInput)
|
||||
const expected = [':storage' + path.sep + '9c9c4ba3-bc1e-441f-9866-c1e9a806e31c' + path.sep + '0.3b88d0dc.png', ':storage' + path.sep + '9c9c4ba3-bc1e-441f-9866-c1e9a806e31c' + path.sep + '2cb8875c.pdf', ':storage' + path.sep + '9c9c4ba3-bc1e-441f-9866-c1e9a806e31c' + path.sep + 'bbf49b02.jpg']
|
||||
expect(actual).toEqual(expect.arrayContaining(expected))
|
||||
})
|
||||
|
||||
@@ -274,6 +319,21 @@ it('should remove the all ":storage" and noteKey references', function () {
|
||||
expect(actual).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
it('should make sure that "removeStorageAndNoteReferences" works with markdown content as well', function () {
|
||||
const noteKey = 'noteKey'
|
||||
const testInput =
|
||||
'Test input' +
|
||||
' \n' +
|
||||
'[' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + noteKey + path.sep + 'pdf.pdf](pdf})'
|
||||
|
||||
const expectedOutput =
|
||||
'Test input' +
|
||||
' \n' +
|
||||
'[' + systemUnderTest.DESTINATION_FOLDER + path.sep + 'pdf.pdf](pdf})'
|
||||
const actual = systemUnderTest.removeStorageAndNoteReferences(testInput, noteKey)
|
||||
expect(actual).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
it('should delete the correct attachment folder if a note is deleted', function () {
|
||||
const dummyStorage = {path: 'dummyStoragePath'}
|
||||
const storageKey = 'storageKey'
|
||||
|
||||
73
tests/lib/escapeHtmlCharacters-test.js
Normal file
73
tests/lib/escapeHtmlCharacters-test.js
Normal file
@@ -0,0 +1,73 @@
|
||||
const { escapeHtmlCharacters } = require('browser/lib/utils')
|
||||
const test = require('ava')
|
||||
|
||||
test('escapeHtmlCharacters should return the original string if nothing needed to escape', t => {
|
||||
const input = 'Nothing to be escaped'
|
||||
const expected = 'Nothing to be escaped'
|
||||
const actual = escapeHtmlCharacters(input)
|
||||
t.is(actual, expected)
|
||||
})
|
||||
|
||||
test('escapeHtmlCharacters should skip code block if that option is enabled', t => {
|
||||
const input = ` <no escape>
|
||||
<escapeMe>`
|
||||
const expected = ` <no escape>
|
||||
<escapeMe>`
|
||||
const actual = escapeHtmlCharacters(input, { detectCodeBlock: true })
|
||||
t.is(actual, expected)
|
||||
})
|
||||
|
||||
test('escapeHtmlCharacters should NOT skip character not in code block but start with 4 spaces', t => {
|
||||
const input = '4 spaces &'
|
||||
const expected = '4 spaces &'
|
||||
const actual = escapeHtmlCharacters(input, { detectCodeBlock: true })
|
||||
t.is(actual, expected)
|
||||
})
|
||||
|
||||
test('escapeHtmlCharacters should NOT skip code block if that option is NOT enabled', t => {
|
||||
const input = ` <no escape>
|
||||
<escapeMe>`
|
||||
const expected = ` <no escape>
|
||||
<escapeMe>`
|
||||
const actual = escapeHtmlCharacters(input)
|
||||
t.is(actual, expected)
|
||||
})
|
||||
|
||||
test("escapeHtmlCharacters should NOT escape & character if it's a part of an escaped character", t => {
|
||||
const input = 'Do not escape & or " but do escape &'
|
||||
const expected = 'Do not escape & or " but do escape &'
|
||||
const actual = escapeHtmlCharacters(input)
|
||||
t.is(actual, expected)
|
||||
})
|
||||
|
||||
test('escapeHtmlCharacters should skip char if in code block', t => {
|
||||
const input = `
|
||||
\`\`\`
|
||||
<dontescapeme>
|
||||
\`\`\`
|
||||
das<das>dasd
|
||||
dasdasdasd
|
||||
\`\`\`
|
||||
<dontescapeme>
|
||||
\`\`\`
|
||||
`
|
||||
const expected = `
|
||||
\`\`\`
|
||||
<dontescapeme>
|
||||
\`\`\`
|
||||
das<das>dasd
|
||||
dasdasdasd
|
||||
\`\`\`
|
||||
<dontescapeme>
|
||||
\`\`\`
|
||||
`
|
||||
const actual = escapeHtmlCharacters(input, { detectCodeBlock: true })
|
||||
t.is(actual, expected)
|
||||
})
|
||||
|
||||
test('escapeHtmlCharacters should return the correct result', t => {
|
||||
const input = '& < > " \''
|
||||
const expected = '& < > " ''
|
||||
const actual = escapeHtmlCharacters(input)
|
||||
t.is(actual, expected)
|
||||
})
|
||||
333
yarn.lock
333
yarn.lock
@@ -79,6 +79,12 @@
|
||||
fs-plus "2.x"
|
||||
optimist "~0.4.0"
|
||||
|
||||
"@susisu/mte-kernel@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@susisu/mte-kernel/-/mte-kernel-2.0.0.tgz#da3354d6a07ea27f36ec91d9fccf6bfa9010d00e"
|
||||
dependencies:
|
||||
meaw "^2.0.0"
|
||||
|
||||
"@types/node@^8.0.24":
|
||||
version "8.10.17"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.17.tgz#d48cf10f0dc6dcf59f827f5a3fc7a4a6004318d3"
|
||||
@@ -1574,6 +1580,26 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1:
|
||||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
chart.js@^2.7.2:
|
||||
version "2.7.2"
|
||||
resolved "http://registry.npm.taobao.org/chart.js/download/chart.js-2.7.2.tgz#3c9fde4dc5b95608211bdefeda7e5d33dffa5714"
|
||||
dependencies:
|
||||
chartjs-color "^2.1.0"
|
||||
moment "^2.10.2"
|
||||
|
||||
chartjs-color-string@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "http://registry.npm.taobao.org/chartjs-color-string/download/chartjs-color-string-0.5.0.tgz#8d3752d8581d86687c35bfe2cb80ac5213ceb8c1"
|
||||
dependencies:
|
||||
color-name "^1.0.0"
|
||||
|
||||
chartjs-color@^2.1.0:
|
||||
version "2.2.0"
|
||||
resolved "http://registry.npm.taobao.org/chartjs-color/download/chartjs-color-2.2.0.tgz#84a2fb755787ed85c39dd6dd8c7b1d88429baeae"
|
||||
dependencies:
|
||||
chartjs-color-string "^0.5.0"
|
||||
color-convert "^0.5.3"
|
||||
|
||||
chokidar@^1.0.0, chokidar@^1.4.2:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
|
||||
@@ -1750,6 +1776,10 @@ collection-visit@^1.0.0:
|
||||
map-visit "^1.0.0"
|
||||
object-visit "^1.0.0"
|
||||
|
||||
color-convert@^0.5.3:
|
||||
version "0.5.3"
|
||||
resolved "http://registry.npm.taobao.org/color-convert/download/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd"
|
||||
|
||||
color-convert@^1.3.0, color-convert@^1.9.0:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed"
|
||||
@@ -1806,6 +1836,10 @@ combined-stream@~0.0.4, combined-stream@~0.0.5:
|
||||
dependencies:
|
||||
delayed-stream "0.0.5"
|
||||
|
||||
commander@2:
|
||||
version "2.16.0"
|
||||
resolved "http://registry.npm.taobao.org/commander/download/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50"
|
||||
|
||||
commander@2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873"
|
||||
@@ -2146,12 +2180,250 @@ currently-unhandled@^0.4.1:
|
||||
dependencies:
|
||||
array-find-index "^1.0.1"
|
||||
|
||||
d3-array@1, d3-array@1.2.1, d3-array@^1.2.0:
|
||||
version "1.2.1"
|
||||
resolved "http://registry.npm.taobao.org/d3-array/download/d3-array-1.2.1.tgz#d1ca33de2f6ac31efadb8e050a021d7e2396d5dc"
|
||||
|
||||
d3-axis@1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "http://registry.npm.taobao.org/d3-axis/download/d3-axis-1.0.8.tgz#31a705a0b535e65759de14173a31933137f18efa"
|
||||
|
||||
d3-brush@1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "http://registry.npm.taobao.org/d3-brush/download/d3-brush-1.0.4.tgz#00c2f238019f24f6c0a194a26d41a1530ffe7bc4"
|
||||
dependencies:
|
||||
d3-dispatch "1"
|
||||
d3-drag "1"
|
||||
d3-interpolate "1"
|
||||
d3-selection "1"
|
||||
d3-transition "1"
|
||||
|
||||
d3-chord@1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "http://registry.npm.taobao.org/d3-chord/download/d3-chord-1.0.4.tgz#7dec4f0ba886f713fe111c45f763414f6f74ca2c"
|
||||
dependencies:
|
||||
d3-array "1"
|
||||
d3-path "1"
|
||||
|
||||
d3-collection@1, d3-collection@1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "http://registry.npm.taobao.org/d3-collection/download/d3-collection-1.0.4.tgz#342dfd12837c90974f33f1cc0a785aea570dcdc2"
|
||||
|
||||
d3-color@1:
|
||||
version "1.2.0"
|
||||
resolved "http://registry.npm.taobao.org/d3-color/download/d3-color-1.2.0.tgz#d1ea19db5859c86854586276ec892cf93148459a"
|
||||
|
||||
d3-color@1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "http://registry.npm.taobao.org/d3-color/download/d3-color-1.0.3.tgz#bc7643fca8e53a8347e2fbdaffa236796b58509b"
|
||||
|
||||
d3-dispatch@1, d3-dispatch@1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "http://registry.npm.taobao.org/d3-dispatch/download/d3-dispatch-1.0.3.tgz#46e1491eaa9b58c358fce5be4e8bed626e7871f8"
|
||||
|
||||
d3-drag@1, d3-drag@1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "http://registry.npm.taobao.org/d3-drag/download/d3-drag-1.2.1.tgz#df8dd4c502fb490fc7462046a8ad98a5c479282d"
|
||||
dependencies:
|
||||
d3-dispatch "1"
|
||||
d3-selection "1"
|
||||
|
||||
d3-dsv@1, d3-dsv@1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "http://registry.npm.taobao.org/d3-dsv/download/d3-dsv-1.0.8.tgz#907e240d57b386618dc56468bacfe76bf19764ae"
|
||||
dependencies:
|
||||
commander "2"
|
||||
iconv-lite "0.4"
|
||||
rw "1"
|
||||
|
||||
d3-ease@1, d3-ease@1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "http://registry.npm.taobao.org/d3-ease/download/d3-ease-1.0.3.tgz#68bfbc349338a380c44d8acc4fbc3304aa2d8c0e"
|
||||
|
||||
d3-force@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "http://registry.npm.taobao.org/d3-force/download/d3-force-1.1.0.tgz#cebf3c694f1078fcc3d4daf8e567b2fbd70d4ea3"
|
||||
dependencies:
|
||||
d3-collection "1"
|
||||
d3-dispatch "1"
|
||||
d3-quadtree "1"
|
||||
d3-timer "1"
|
||||
|
||||
d3-format@1:
|
||||
version "1.3.0"
|
||||
resolved "http://registry.npm.taobao.org/d3-format/download/d3-format-1.3.0.tgz#a3ac44269a2011cdb87c7b5693040c18cddfff11"
|
||||
|
||||
d3-format@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "http://registry.npm.taobao.org/d3-format/download/d3-format-1.2.2.tgz#1a39c479c8a57fe5051b2e67a3bee27061a74e7a"
|
||||
|
||||
d3-geo@1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "http://registry.npm.taobao.org/d3-geo/download/d3-geo-1.9.1.tgz#157e3b0f917379d0f73bebfff3be537f49fa7356"
|
||||
dependencies:
|
||||
d3-array "1"
|
||||
|
||||
d3-hierarchy@1.1.5:
|
||||
version "1.1.5"
|
||||
resolved "http://registry.npm.taobao.org/d3-hierarchy/download/d3-hierarchy-1.1.5.tgz#a1c845c42f84a206bcf1c01c01098ea4ddaa7a26"
|
||||
|
||||
d3-interpolate@1:
|
||||
version "1.2.0"
|
||||
resolved "http://registry.npm.taobao.org/d3-interpolate/download/d3-interpolate-1.2.0.tgz#40d81bd8e959ff021c5ea7545bc79b8d22331c41"
|
||||
dependencies:
|
||||
d3-color "1"
|
||||
|
||||
d3-interpolate@1.1.6:
|
||||
version "1.1.6"
|
||||
resolved "http://registry.npm.taobao.org/d3-interpolate/download/d3-interpolate-1.1.6.tgz#2cf395ae2381804df08aa1bf766b7f97b5f68fb6"
|
||||
dependencies:
|
||||
d3-color "1"
|
||||
|
||||
d3-path@1, d3-path@1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "http://registry.npm.taobao.org/d3-path/download/d3-path-1.0.5.tgz#241eb1849bd9e9e8021c0d0a799f8a0e8e441764"
|
||||
|
||||
d3-polygon@1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "http://registry.npm.taobao.org/d3-polygon/download/d3-polygon-1.0.3.tgz#16888e9026460933f2b179652ad378224d382c62"
|
||||
|
||||
d3-quadtree@1, d3-quadtree@1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "http://registry.npm.taobao.org/d3-quadtree/download/d3-quadtree-1.0.3.tgz#ac7987e3e23fe805a990f28e1b50d38fcb822438"
|
||||
|
||||
d3-queue@3.0.7:
|
||||
version "3.0.7"
|
||||
resolved "http://registry.npm.taobao.org/d3-queue/download/d3-queue-3.0.7.tgz#c93a2e54b417c0959129d7d73f6cf7d4292e7618"
|
||||
|
||||
d3-random@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "http://registry.npm.taobao.org/d3-random/download/d3-random-1.1.0.tgz#6642e506c6fa3a648595d2b2469788a8d12529d3"
|
||||
|
||||
d3-request@1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "http://registry.npm.taobao.org/d3-request/download/d3-request-1.0.6.tgz#a1044a9ef4ec28c824171c9379fae6d79474b19f"
|
||||
dependencies:
|
||||
d3-collection "1"
|
||||
d3-dispatch "1"
|
||||
d3-dsv "1"
|
||||
xmlhttprequest "1"
|
||||
|
||||
d3-scale@1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "http://registry.npm.taobao.org/d3-scale/download/d3-scale-1.0.7.tgz#fa90324b3ea8a776422bd0472afab0b252a0945d"
|
||||
dependencies:
|
||||
d3-array "^1.2.0"
|
||||
d3-collection "1"
|
||||
d3-color "1"
|
||||
d3-format "1"
|
||||
d3-interpolate "1"
|
||||
d3-time "1"
|
||||
d3-time-format "2"
|
||||
|
||||
d3-selection@1, d3-selection@1.3.0, d3-selection@^1.1.0:
|
||||
version "1.3.0"
|
||||
resolved "http://registry.npm.taobao.org/d3-selection/download/d3-selection-1.3.0.tgz#d53772382d3dc4f7507bfb28bcd2d6aed2a0ad6d"
|
||||
|
||||
d3-shape@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "http://registry.npm.taobao.org/d3-shape/download/d3-shape-1.2.0.tgz#45d01538f064bafd05ea3d6d2cb748fd8c41f777"
|
||||
dependencies:
|
||||
d3-path "1"
|
||||
|
||||
d3-time-format@2, d3-time-format@2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "http://registry.npm.taobao.org/d3-time-format/download/d3-time-format-2.1.1.tgz#85b7cdfbc9ffca187f14d3c456ffda268081bb31"
|
||||
dependencies:
|
||||
d3-time "1"
|
||||
|
||||
d3-time@1, d3-time@1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "http://registry.npm.taobao.org/d3-time/download/d3-time-1.0.8.tgz#dbd2d6007bf416fe67a76d17947b784bffea1e84"
|
||||
|
||||
d3-timer@1, d3-timer@1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "http://registry.npm.taobao.org/d3-timer/download/d3-timer-1.0.7.tgz#df9650ca587f6c96607ff4e60cc38229e8dd8531"
|
||||
|
||||
d3-transition@1, d3-transition@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "http://registry.npm.taobao.org/d3-transition/download/d3-transition-1.1.1.tgz#d8ef89c3b848735b060e54a39b32aaebaa421039"
|
||||
dependencies:
|
||||
d3-color "1"
|
||||
d3-dispatch "1"
|
||||
d3-ease "1"
|
||||
d3-interpolate "1"
|
||||
d3-selection "^1.1.0"
|
||||
d3-timer "1"
|
||||
|
||||
d3-voronoi@1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "http://registry.npm.taobao.org/d3-voronoi/download/d3-voronoi-1.1.2.tgz#1687667e8f13a2d158c80c1480c5a29cb0d8973c"
|
||||
|
||||
d3-zoom@1.7.1:
|
||||
version "1.7.1"
|
||||
resolved "http://registry.npm.taobao.org/d3-zoom/download/d3-zoom-1.7.1.tgz#02f43b3c3e2db54f364582d7e4a236ccc5506b63"
|
||||
dependencies:
|
||||
d3-dispatch "1"
|
||||
d3-drag "1"
|
||||
d3-interpolate "1"
|
||||
d3-selection "1"
|
||||
d3-transition "1"
|
||||
|
||||
d3@^4.13.0:
|
||||
version "4.13.0"
|
||||
resolved "http://registry.npm.taobao.org/d3/download/d3-4.13.0.tgz#ab236ff8cf0cfc27a81e69bf2fb7518bc9b4f33d"
|
||||
dependencies:
|
||||
d3-array "1.2.1"
|
||||
d3-axis "1.0.8"
|
||||
d3-brush "1.0.4"
|
||||
d3-chord "1.0.4"
|
||||
d3-collection "1.0.4"
|
||||
d3-color "1.0.3"
|
||||
d3-dispatch "1.0.3"
|
||||
d3-drag "1.2.1"
|
||||
d3-dsv "1.0.8"
|
||||
d3-ease "1.0.3"
|
||||
d3-force "1.1.0"
|
||||
d3-format "1.2.2"
|
||||
d3-geo "1.9.1"
|
||||
d3-hierarchy "1.1.5"
|
||||
d3-interpolate "1.1.6"
|
||||
d3-path "1.0.5"
|
||||
d3-polygon "1.0.3"
|
||||
d3-quadtree "1.0.3"
|
||||
d3-queue "3.0.7"
|
||||
d3-random "1.1.0"
|
||||
d3-request "1.0.6"
|
||||
d3-scale "1.0.7"
|
||||
d3-selection "1.3.0"
|
||||
d3-shape "1.2.0"
|
||||
d3-time "1.0.8"
|
||||
d3-time-format "2.1.1"
|
||||
d3-timer "1.0.7"
|
||||
d3-transition "1.1.1"
|
||||
d3-voronoi "1.1.2"
|
||||
d3-zoom "1.7.1"
|
||||
|
||||
d@1:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"
|
||||
dependencies:
|
||||
es5-ext "^0.10.9"
|
||||
|
||||
dagre-d3-renderer@^0.5.8:
|
||||
version "0.5.8"
|
||||
resolved "http://registry.npm.taobao.org/dagre-d3-renderer/download/dagre-d3-renderer-0.5.8.tgz#aa071bb71d3c4d67426925906f3f6ddead49c1a3"
|
||||
dependencies:
|
||||
dagre-layout "^0.8.8"
|
||||
lodash "^4.17.5"
|
||||
|
||||
dagre-layout@^0.8.8:
|
||||
version "0.8.8"
|
||||
resolved "http://registry.npm.taobao.org/dagre-layout/download/dagre-layout-0.8.8.tgz#9b6792f24229f402441c14162c1049e3f261f6d9"
|
||||
dependencies:
|
||||
graphlibrary "^2.2.0"
|
||||
lodash "^4.17.5"
|
||||
|
||||
dashdash@^1.12.0:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
|
||||
@@ -3685,6 +3957,12 @@ graceful-fs@~1.2.0:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364"
|
||||
|
||||
graphlibrary@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "http://registry.npm.taobao.org/graphlibrary/download/graphlibrary-2.2.0.tgz#017a14899775228dec4497a39babfdd6bf56eac6"
|
||||
dependencies:
|
||||
lodash "^4.17.5"
|
||||
|
||||
growly@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
|
||||
@@ -3874,6 +4152,10 @@ hawk@~2.3.0:
|
||||
hoek "2.x.x"
|
||||
sntp "1.x.x"
|
||||
|
||||
he@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "http://registry.npm.taobao.org/he/download/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
||||
|
||||
highlight.js@^9.3.0:
|
||||
version "9.12.0"
|
||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e"
|
||||
@@ -4037,16 +4319,16 @@ i18n-2@^0.7.2:
|
||||
debug "^3.1.0"
|
||||
sprintf "^0.1.5"
|
||||
|
||||
iconv-lite@0.4.19:
|
||||
version "0.4.19"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
|
||||
|
||||
iconv-lite@^0.4.19, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
|
||||
iconv-lite@0.4, iconv-lite@^0.4.19, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
|
||||
version "0.4.23"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
|
||||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3"
|
||||
|
||||
iconv-lite@0.4.19:
|
||||
version "0.4.19"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
|
||||
|
||||
iconv-lite@~0.2.11:
|
||||
version "0.2.11"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.2.11.tgz#1ce60a3a57864a292d1321ff4609ca4bb965adc8"
|
||||
@@ -5298,7 +5580,7 @@ lodash@^3.5.0:
|
||||
version "3.10.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
|
||||
|
||||
lodash@^4.0.0, lodash@^4.0.1, lodash@^4.11.1, lodash@^4.12.0, lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1:
|
||||
lodash@^4.0.0, lodash@^4.0.1, lodash@^4.11.1, lodash@^4.12.0, lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1:
|
||||
version "4.17.10"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
|
||||
|
||||
@@ -5368,9 +5650,9 @@ map-visit@^1.0.0:
|
||||
dependencies:
|
||||
object-visit "^1.0.0"
|
||||
|
||||
"markdown-it-admonition@https://github.com/johannbre/markdown-it-admonition.git":
|
||||
version "1.0.2"
|
||||
resolved "https://github.com/johannbre/markdown-it-admonition.git#e0c0fcd59e9119d6d60ed209aa3d0f1177ec0166"
|
||||
markdown-it-admonition@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it-admonition/-/markdown-it-admonition-1.0.4.tgz#d7bbc7eb1fe6168fc8cc304de7a9d8c993acb2f5"
|
||||
|
||||
markdown-it-emoji@^1.1.1:
|
||||
version "1.4.0"
|
||||
@@ -5470,6 +5752,10 @@ mdurl@^1.0.1, mdurl@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||
|
||||
meaw@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/meaw/-/meaw-2.0.0.tgz#7c3467efee5618cb865661dfaa38d6948dc23f7a"
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
@@ -5527,6 +5813,19 @@ merge@^1.1.3:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da"
|
||||
|
||||
mermaid@^8.0.0-rc.8:
|
||||
version "8.0.0-rc.8"
|
||||
resolved "http://registry.npm.taobao.org/mermaid/download/mermaid-8.0.0-rc.8.tgz#74ed54d0d46e9ee71c4db2730b2d83d516a21e72"
|
||||
dependencies:
|
||||
d3 "^4.13.0"
|
||||
dagre-d3-renderer "^0.5.8"
|
||||
dagre-layout "^0.8.8"
|
||||
graphlibrary "^2.2.0"
|
||||
he "^1.1.1"
|
||||
lodash "^4.17.5"
|
||||
moment "^2.21.0"
|
||||
scope-css "^1.0.5"
|
||||
|
||||
methods@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
@@ -5696,6 +5995,10 @@ mock-require@^3.0.1:
|
||||
get-caller-file "^1.0.2"
|
||||
normalize-path "^2.1.1"
|
||||
|
||||
moment@^2.10.2, moment@^2.21.0:
|
||||
version "2.22.2"
|
||||
resolved "http://registry.npm.taobao.org/moment/download/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
|
||||
|
||||
moment@^2.10.3:
|
||||
version "2.22.1"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.1.tgz#529a2e9bf973f259c9643d237fda84de3a26e8ad"
|
||||
@@ -7345,6 +7648,10 @@ run-series@^1.1.1:
|
||||
version "1.1.8"
|
||||
resolved "https://registry.yarnpkg.com/run-series/-/run-series-1.1.8.tgz#2c4558f49221e01cd6371ff4e0a1e203e460fc36"
|
||||
|
||||
rw@1:
|
||||
version "1.3.3"
|
||||
resolved "http://registry.npm.taobao.org/rw/download/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
|
||||
|
||||
rx-lite@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
|
||||
@@ -7422,6 +7729,10 @@ sax@>=0.6.0, sax@^1.2.1, sax@^1.2.4, sax@~1.2.1:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
|
||||
scope-css@^1.0.5:
|
||||
version "1.1.0"
|
||||
resolved "http://registry.npm.taobao.org/scope-css/download/scope-css-1.1.0.tgz#74eff45461bc9d3f3b29ed575b798cd722fa1256"
|
||||
|
||||
semver-diff@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
|
||||
@@ -8822,6 +9133,10 @@ xmldom@0.1.x:
|
||||
version "0.1.27"
|
||||
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9"
|
||||
|
||||
xmlhttprequest@1:
|
||||
version "1.8.0"
|
||||
resolved "http://registry.npm.taobao.org/xmlhttprequest/download/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
|
||||
|
||||
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
|
||||
|
||||
Reference in New Issue
Block a user