Improve behaviour when adding formatting elements from library
This commit is contained in:
parent
ed1110d74f
commit
d103dc0574
|
@ -253,51 +253,61 @@
|
||||||
{
|
{
|
||||||
code: '**{text}**',
|
code: '**{text}**',
|
||||||
preview: 'A -> B: **bold**',
|
preview: 'A -> B: **bold**',
|
||||||
|
surround: true,
|
||||||
title: 'Bold markdown',
|
title: 'Bold markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '_{text}_',
|
code: '_{text}_',
|
||||||
preview: 'A -> B: _italic_',
|
preview: 'A -> B: _italic_',
|
||||||
|
surround: true,
|
||||||
title: 'Italic markdown',
|
title: 'Italic markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '~{text}~',
|
code: '~{text}~',
|
||||||
preview: 'A -> B: ~strikeout~',
|
preview: 'A -> B: ~strikeout~',
|
||||||
|
surround: true,
|
||||||
title: 'Strikeout markdown',
|
title: 'Strikeout markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '<u>{text}</u>',
|
code: '<u>{text}</u>',
|
||||||
preview: 'A -> B: <u>underline</u>',
|
preview: 'A -> B: <u>underline</u>',
|
||||||
|
surround: true,
|
||||||
title: 'Underline markdown',
|
title: 'Underline markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '<o>{text}</o>',
|
code: '<o>{text}</o>',
|
||||||
preview: 'A -> B: <o>overline</o>',
|
preview: 'A -> B: <o>overline</o>',
|
||||||
|
surround: true,
|
||||||
title: 'Overline markdown',
|
title: 'Overline markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '<sup>{text}</sup>',
|
code: '<sup>{text}</sup>',
|
||||||
preview: 'A -> B: super<sup>script</sup>',
|
preview: 'A -> B: super<sup>script</sup>',
|
||||||
|
surround: true,
|
||||||
title: 'Superscript markdown',
|
title: 'Superscript markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '<sub>{text}</sub>',
|
code: '<sub>{text}</sub>',
|
||||||
preview: 'A -> B: sub<sub>script</sub>',
|
preview: 'A -> B: sub<sub>script</sub>',
|
||||||
|
surround: true,
|
||||||
title: 'Subscript markdown',
|
title: 'Subscript markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '`{text}`',
|
code: '`{text}`',
|
||||||
preview: 'A -> B: `mono`',
|
preview: 'A -> B: `mono`',
|
||||||
|
surround: true,
|
||||||
title: 'Monospace markdown',
|
title: 'Monospace markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '<red>{text}</red>',
|
code: '<red>{text}</red>',
|
||||||
preview: 'A -> B: <red>red</red>',
|
preview: 'A -> B: <red>red</red>',
|
||||||
|
surround: true,
|
||||||
title: 'Red markdown',
|
title: 'Red markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '<highlight>{text}</highlight>',
|
code: '<highlight>{text}</highlight>',
|
||||||
preview: 'A -> B: <highlight>highlight</highlight>',
|
preview: 'A -> B: <highlight>highlight</highlight>',
|
||||||
|
surround: true,
|
||||||
title: 'Highlight markdown',
|
title: 'Highlight markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -870,6 +880,15 @@
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function lineWithinRange(doc, ln, start, end) {
|
||||||
|
const full = doc.getLine(ln);
|
||||||
|
const begin = (ln === start.line) ? start.ch : 0;
|
||||||
|
return {
|
||||||
|
chOffset: begin,
|
||||||
|
line: (ln === end.line) ? full.slice(begin, end.ch) : full.slice(begin),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
class CodeEditor extends EventObject {
|
class CodeEditor extends EventObject {
|
||||||
constructor(dom, container, {
|
constructor(dom, container, {
|
||||||
mode = '',
|
mode = '',
|
||||||
|
@ -974,8 +993,8 @@
|
||||||
this.code.off('cursorActivity', move);
|
this.code.off('cursorActivity', move);
|
||||||
this.paramMarkers.forEach((m) => m.clear());
|
this.paramMarkers.forEach((m) => m.clear());
|
||||||
this.paramMarkers = null;
|
this.paramMarkers = null;
|
||||||
|
this.code.setCursor(endBookmark.find());
|
||||||
endBookmark.clear();
|
endBookmark.clear();
|
||||||
this.code.setCursor(end);
|
|
||||||
this.cancelParams = null;
|
this.cancelParams = null;
|
||||||
this.advanceParams = null;
|
this.advanceParams = null;
|
||||||
};
|
};
|
||||||
|
@ -1001,12 +1020,12 @@
|
||||||
|
|
||||||
const doc = this.code.getDoc();
|
const doc = this.code.getDoc();
|
||||||
const ranges = [];
|
const ranges = [];
|
||||||
let {ch} = start;
|
const end = endBookmark.find();
|
||||||
for(let ln = start.line; ln < endBookmark.find().line; ++ ln) {
|
for(let ln = start.line; ln <= end.line; ++ ln) {
|
||||||
const line = doc.getLine(ln).slice(ch);
|
const {chOffset, line} = lineWithinRange(doc, ln, start, end);
|
||||||
for(let p = 0; (p = line.indexOf(tok, p)) !== -1; p += tok.length) {
|
for(let p = 0; (p = line.indexOf(tok, p)) !== -1; p += tok.length) {
|
||||||
const anchor = {ch: p, line: ln};
|
const anchor = {ch: chOffset + p, line: ln};
|
||||||
const head = {ch: p + tok.length, line: ln};
|
const head = {ch: chOffset + p + tok.length, line: ln};
|
||||||
ranges.push({anchor, head});
|
ranges.push({anchor, head});
|
||||||
this.paramMarkers.push(doc.markText(anchor, head, {
|
this.paramMarkers.push(doc.markText(anchor, head, {
|
||||||
className: 'param',
|
className: 'param',
|
||||||
|
@ -1015,7 +1034,6 @@
|
||||||
inclusiveRight: true,
|
inclusiveRight: true,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
ch = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ranges.length > 0) {
|
if(ranges.length > 0) {
|
||||||
|
@ -1025,11 +1043,39 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addCodeBlock(block) {
|
hasSelection() {
|
||||||
const lines = block.split('\n').length;
|
const from = this.code.getCursor('from');
|
||||||
|
const to = this.code.getCursor('to');
|
||||||
|
return from.line !== to.line || from.ch !== to.ch;
|
||||||
|
}
|
||||||
|
|
||||||
this.code.focus();
|
internalAddSurroundCode(block) {
|
||||||
|
if(this.enhanced) {
|
||||||
|
if(this.hasSelection()) {
|
||||||
|
this.code.replaceSelection(
|
||||||
|
block.replace(/\{.*\}/, this.code.getSelection()),
|
||||||
|
'end',
|
||||||
|
'library'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const cur = this.code.getCursor('head');
|
||||||
|
this.code.replaceSelection(block, null, 'library');
|
||||||
|
const end = {ch: cur.ch + block.length, line: cur.line};
|
||||||
|
this.enterParams(cur, end, block);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const value = this.value();
|
||||||
|
const s1 = this.code.element.selectionStart;
|
||||||
|
const s2 = this.code.element.selectionEnd;
|
||||||
|
const wrapped = block.replace(/\{.*\}/, value.substring(s1, s2));
|
||||||
|
this.code
|
||||||
|
.val(value.substr(0, s1) + wrapped + value.substr(s2))
|
||||||
|
.select(s1 + wrapped.length);
|
||||||
|
this.trigger('change');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internalAddIndependentCode(block) {
|
||||||
if(this.enhanced) {
|
if(this.enhanced) {
|
||||||
const cur = this.code.getCursor('head');
|
const cur = this.code.getCursor('head');
|
||||||
const pos = {ch: 0, line: cur.line + ((cur.ch > 0) ? 1 : 0)};
|
const pos = {ch: 0, line: cur.line + ((cur.ch > 0) ? 1 : 0)};
|
||||||
|
@ -1038,6 +1084,7 @@
|
||||||
replaced = '\n' + replaced;
|
replaced = '\n' + replaced;
|
||||||
}
|
}
|
||||||
this.code.replaceRange(replaced, pos, null, 'library');
|
this.code.replaceRange(replaced, pos, null, 'library');
|
||||||
|
const lines = block.split('\n').length;
|
||||||
const end = {ch: 0, line: pos.line + lines};
|
const end = {ch: 0, line: pos.line + lines};
|
||||||
this.enterParams(pos, end, block);
|
this.enterParams(pos, end, block);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1055,6 +1102,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addCodeBlock(block, surround = false) {
|
||||||
|
this.code.focus();
|
||||||
|
|
||||||
|
if(surround) {
|
||||||
|
this.internalAddSurroundCode(block);
|
||||||
|
} else {
|
||||||
|
this.internalAddIndependentCode(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
value() {
|
value() {
|
||||||
if(this.enhanced) {
|
if(this.enhanced) {
|
||||||
return this.code.getDoc().getValue();
|
return this.code.getDoc().getValue();
|
||||||
|
@ -1645,7 +1702,10 @@
|
||||||
.setClass('library-item')
|
.setClass('library-item')
|
||||||
.add(holdInner)
|
.add(holdInner)
|
||||||
.fastClick()
|
.fastClick()
|
||||||
.on('click', () => this.code.addCodeBlock(lib.code))
|
.on('click', () => this.code.addCodeBlock(
|
||||||
|
lib.code,
|
||||||
|
lib.surround
|
||||||
|
))
|
||||||
.attach(container);
|
.attach(container);
|
||||||
|
|
||||||
return this.diagram.clone({
|
return this.diagram.clone({
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -39,6 +39,15 @@ function findNextToken(block, skip) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function lineWithinRange(doc, ln, start, end) {
|
||||||
|
const full = doc.getLine(ln);
|
||||||
|
const begin = (ln === start.line) ? start.ch : 0;
|
||||||
|
return {
|
||||||
|
chOffset: begin,
|
||||||
|
line: (ln === end.line) ? full.slice(begin, end.ch) : full.slice(begin),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default class CodeEditor extends EventObject {
|
export default class CodeEditor extends EventObject {
|
||||||
constructor(dom, container, {
|
constructor(dom, container, {
|
||||||
mode = '',
|
mode = '',
|
||||||
|
@ -143,8 +152,8 @@ export default class CodeEditor extends EventObject {
|
||||||
this.code.off('cursorActivity', move);
|
this.code.off('cursorActivity', move);
|
||||||
this.paramMarkers.forEach((m) => m.clear());
|
this.paramMarkers.forEach((m) => m.clear());
|
||||||
this.paramMarkers = null;
|
this.paramMarkers = null;
|
||||||
|
this.code.setCursor(endBookmark.find());
|
||||||
endBookmark.clear();
|
endBookmark.clear();
|
||||||
this.code.setCursor(end);
|
|
||||||
this.cancelParams = null;
|
this.cancelParams = null;
|
||||||
this.advanceParams = null;
|
this.advanceParams = null;
|
||||||
};
|
};
|
||||||
|
@ -170,12 +179,12 @@ export default class CodeEditor extends EventObject {
|
||||||
|
|
||||||
const doc = this.code.getDoc();
|
const doc = this.code.getDoc();
|
||||||
const ranges = [];
|
const ranges = [];
|
||||||
let {ch} = start;
|
const end = endBookmark.find();
|
||||||
for(let ln = start.line; ln < endBookmark.find().line; ++ ln) {
|
for(let ln = start.line; ln <= end.line; ++ ln) {
|
||||||
const line = doc.getLine(ln).slice(ch);
|
const {chOffset, line} = lineWithinRange(doc, ln, start, end);
|
||||||
for(let p = 0; (p = line.indexOf(tok, p)) !== -1; p += tok.length) {
|
for(let p = 0; (p = line.indexOf(tok, p)) !== -1; p += tok.length) {
|
||||||
const anchor = {ch: p, line: ln};
|
const anchor = {ch: chOffset + p, line: ln};
|
||||||
const head = {ch: p + tok.length, line: ln};
|
const head = {ch: chOffset + p + tok.length, line: ln};
|
||||||
ranges.push({anchor, head});
|
ranges.push({anchor, head});
|
||||||
this.paramMarkers.push(doc.markText(anchor, head, {
|
this.paramMarkers.push(doc.markText(anchor, head, {
|
||||||
className: 'param',
|
className: 'param',
|
||||||
|
@ -184,7 +193,6 @@ export default class CodeEditor extends EventObject {
|
||||||
inclusiveRight: true,
|
inclusiveRight: true,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
ch = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ranges.length > 0) {
|
if(ranges.length > 0) {
|
||||||
|
@ -194,11 +202,39 @@ export default class CodeEditor extends EventObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addCodeBlock(block) {
|
hasSelection() {
|
||||||
const lines = block.split('\n').length;
|
const from = this.code.getCursor('from');
|
||||||
|
const to = this.code.getCursor('to');
|
||||||
|
return from.line !== to.line || from.ch !== to.ch;
|
||||||
|
}
|
||||||
|
|
||||||
this.code.focus();
|
internalAddSurroundCode(block) {
|
||||||
|
if(this.enhanced) {
|
||||||
|
if(this.hasSelection()) {
|
||||||
|
this.code.replaceSelection(
|
||||||
|
block.replace(/\{.*\}/, this.code.getSelection()),
|
||||||
|
'end',
|
||||||
|
'library'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const cur = this.code.getCursor('head');
|
||||||
|
this.code.replaceSelection(block, null, 'library');
|
||||||
|
const end = {ch: cur.ch + block.length, line: cur.line};
|
||||||
|
this.enterParams(cur, end, block);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const value = this.value();
|
||||||
|
const s1 = this.code.element.selectionStart;
|
||||||
|
const s2 = this.code.element.selectionEnd;
|
||||||
|
const wrapped = block.replace(/\{.*\}/, value.substring(s1, s2));
|
||||||
|
this.code
|
||||||
|
.val(value.substr(0, s1) + wrapped + value.substr(s2))
|
||||||
|
.select(s1 + wrapped.length);
|
||||||
|
this.trigger('change');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internalAddIndependentCode(block) {
|
||||||
if(this.enhanced) {
|
if(this.enhanced) {
|
||||||
const cur = this.code.getCursor('head');
|
const cur = this.code.getCursor('head');
|
||||||
const pos = {ch: 0, line: cur.line + ((cur.ch > 0) ? 1 : 0)};
|
const pos = {ch: 0, line: cur.line + ((cur.ch > 0) ? 1 : 0)};
|
||||||
|
@ -207,6 +243,7 @@ export default class CodeEditor extends EventObject {
|
||||||
replaced = '\n' + replaced;
|
replaced = '\n' + replaced;
|
||||||
}
|
}
|
||||||
this.code.replaceRange(replaced, pos, null, 'library');
|
this.code.replaceRange(replaced, pos, null, 'library');
|
||||||
|
const lines = block.split('\n').length;
|
||||||
const end = {ch: 0, line: pos.line + lines};
|
const end = {ch: 0, line: pos.line + lines};
|
||||||
this.enterParams(pos, end, block);
|
this.enterParams(pos, end, block);
|
||||||
} else {
|
} else {
|
||||||
|
@ -224,6 +261,16 @@ export default class CodeEditor extends EventObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addCodeBlock(block, surround = false) {
|
||||||
|
this.code.focus();
|
||||||
|
|
||||||
|
if(surround) {
|
||||||
|
this.internalAddSurroundCode(block);
|
||||||
|
} else {
|
||||||
|
this.internalAddIndependentCode(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
value() {
|
value() {
|
||||||
if(this.enhanced) {
|
if(this.enhanced) {
|
||||||
return this.code.getDoc().getValue();
|
return this.code.getDoc().getValue();
|
||||||
|
|
|
@ -250,51 +250,61 @@ export default [
|
||||||
{
|
{
|
||||||
code: '**{text}**',
|
code: '**{text}**',
|
||||||
preview: 'A -> B: **bold**',
|
preview: 'A -> B: **bold**',
|
||||||
|
surround: true,
|
||||||
title: 'Bold markdown',
|
title: 'Bold markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '_{text}_',
|
code: '_{text}_',
|
||||||
preview: 'A -> B: _italic_',
|
preview: 'A -> B: _italic_',
|
||||||
|
surround: true,
|
||||||
title: 'Italic markdown',
|
title: 'Italic markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '~{text}~',
|
code: '~{text}~',
|
||||||
preview: 'A -> B: ~strikeout~',
|
preview: 'A -> B: ~strikeout~',
|
||||||
|
surround: true,
|
||||||
title: 'Strikeout markdown',
|
title: 'Strikeout markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '<u>{text}</u>',
|
code: '<u>{text}</u>',
|
||||||
preview: 'A -> B: <u>underline</u>',
|
preview: 'A -> B: <u>underline</u>',
|
||||||
|
surround: true,
|
||||||
title: 'Underline markdown',
|
title: 'Underline markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '<o>{text}</o>',
|
code: '<o>{text}</o>',
|
||||||
preview: 'A -> B: <o>overline</o>',
|
preview: 'A -> B: <o>overline</o>',
|
||||||
|
surround: true,
|
||||||
title: 'Overline markdown',
|
title: 'Overline markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '<sup>{text}</sup>',
|
code: '<sup>{text}</sup>',
|
||||||
preview: 'A -> B: super<sup>script</sup>',
|
preview: 'A -> B: super<sup>script</sup>',
|
||||||
|
surround: true,
|
||||||
title: 'Superscript markdown',
|
title: 'Superscript markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '<sub>{text}</sub>',
|
code: '<sub>{text}</sub>',
|
||||||
preview: 'A -> B: sub<sub>script</sub>',
|
preview: 'A -> B: sub<sub>script</sub>',
|
||||||
|
surround: true,
|
||||||
title: 'Subscript markdown',
|
title: 'Subscript markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '`{text}`',
|
code: '`{text}`',
|
||||||
preview: 'A -> B: `mono`',
|
preview: 'A -> B: `mono`',
|
||||||
|
surround: true,
|
||||||
title: 'Monospace markdown',
|
title: 'Monospace markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '<red>{text}</red>',
|
code: '<red>{text}</red>',
|
||||||
preview: 'A -> B: <red>red</red>',
|
preview: 'A -> B: <red>red</red>',
|
||||||
|
surround: true,
|
||||||
title: 'Red markdown',
|
title: 'Red markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: '<highlight>{text}</highlight>',
|
code: '<highlight>{text}</highlight>',
|
||||||
preview: 'A -> B: <highlight>highlight</highlight>',
|
preview: 'A -> B: <highlight>highlight</highlight>',
|
||||||
|
surround: true,
|
||||||
title: 'Highlight markdown',
|
title: 'Highlight markdown',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -381,7 +381,10 @@ export default class Interface {
|
||||||
.setClass('library-item')
|
.setClass('library-item')
|
||||||
.add(holdInner)
|
.add(holdInner)
|
||||||
.fastClick()
|
.fastClick()
|
||||||
.on('click', () => this.code.addCodeBlock(lib.code))
|
.on('click', () => this.code.addCodeBlock(
|
||||||
|
lib.code,
|
||||||
|
lib.surround
|
||||||
|
))
|
||||||
.attach(container);
|
.attach(container);
|
||||||
|
|
||||||
return this.diagram.clone({
|
return this.diagram.clone({
|
||||||
|
|
Loading…
Reference in New Issue