Support open-in-editor URLs [#59]
This commit is contained in:
parent
bdd8122a9f
commit
ed1110d74f
|
@ -370,6 +370,10 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getRawHash() {
|
||||||
|
return getHash();
|
||||||
|
}
|
||||||
|
|
||||||
maxSlots() {
|
maxSlots() {
|
||||||
// Capacity of localStorage is limited
|
// Capacity of localStorage is limited
|
||||||
// So avoid allowing too many documents
|
// So avoid allowing too many documents
|
||||||
|
@ -1176,20 +1180,34 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
class URLExporter {
|
class URLExporter {
|
||||||
constructor(base = '') {
|
constructor(renderBase = '', editBase = '') {
|
||||||
this.base = base;
|
this.renderBase = renderBase;
|
||||||
|
this.editBase = editBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
setBase(base) {
|
setRenderBase(renderBase) {
|
||||||
this.base = base;
|
this.renderBase = renderBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
_convertCode(code) {
|
setEditBase(editBase) {
|
||||||
return code
|
this.editBase = editBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
_convertCode(code, keepBlankLines = false) {
|
||||||
|
let lines = code
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.map(encodeURIComponent)
|
.map(encodeURIComponent);
|
||||||
.filter((ln) => ln !== '')
|
|
||||||
.join('/');
|
if(keepBlankLines) {
|
||||||
|
// Always trim trailing blank lines
|
||||||
|
while(lines.length > 0 && lines[lines.length - 1] === '') {
|
||||||
|
-- lines.length;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lines = lines.filter((ln) => ln !== '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines.join('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
_convertWidthHeight(width, height) {
|
_convertWidthHeight(width, height) {
|
||||||
|
@ -1220,14 +1238,22 @@
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
getURL(code, size = {}) {
|
getRenderURL(code, size = {}) {
|
||||||
return (
|
return (
|
||||||
this.base +
|
this.renderBase +
|
||||||
this._convertSize(size) +
|
this._convertSize(size) +
|
||||||
this._convertCode(code) +
|
this._convertCode(code) +
|
||||||
'.svg'
|
'.svg'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getEditURL(code) {
|
||||||
|
return (
|
||||||
|
this.editBase +
|
||||||
|
'#edit:' +
|
||||||
|
this._convertCode(code, true)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VoidStorage {
|
class VoidStorage {
|
||||||
|
@ -1277,6 +1303,14 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setDocumentTitle(diagramTitle) {
|
||||||
|
let title = diagramTitle.trim();
|
||||||
|
if(title.length > 20) {
|
||||||
|
title = title.substr(0, 18).trim() + '\u2026';
|
||||||
|
}
|
||||||
|
document.title = (title ? `${title} \u2014 ` : '') + 'Sequence Diagram';
|
||||||
|
}
|
||||||
|
|
||||||
class Interface {
|
class Interface {
|
||||||
constructor({
|
constructor({
|
||||||
sequenceDiagram,
|
sequenceDiagram,
|
||||||
|
@ -1313,6 +1347,7 @@
|
||||||
this.diagram
|
this.diagram
|
||||||
.on('render', () => {
|
.on('render', () => {
|
||||||
this.updateMinSize(this.diagram.getSize());
|
this.updateMinSize(this.diagram.getSize());
|
||||||
|
setDocumentTitle(this.diagram.getTitle());
|
||||||
this.pngDirty = true;
|
this.pngDirty = true;
|
||||||
})
|
})
|
||||||
.on('mouseover', (element) => this.code.markLineHover(element.ln))
|
.on('mouseover', (element) => this.code.markLineHover(element.ln))
|
||||||
|
@ -1365,6 +1400,32 @@
|
||||||
setTimeout(() => copied.styles({'display': 'none'}), 1500);
|
setTimeout(() => copied.styles({'display': 'none'}), 1500);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updateMode = () => {
|
||||||
|
this.renderOpts.styles({
|
||||||
|
'display': this.modeEdit.element.checked ? 'none' : 'block',
|
||||||
|
});
|
||||||
|
this._refreshURL();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.modeRender = this.dom.el('input').attrs({
|
||||||
|
'checked': 'checked',
|
||||||
|
'name': 'export-mode',
|
||||||
|
'type': 'radio',
|
||||||
|
'value': 'render',
|
||||||
|
}).on('change', updateMode);
|
||||||
|
|
||||||
|
this.modeEdit = this.dom.el('input').attrs({
|
||||||
|
'name': 'export-mode',
|
||||||
|
'type': 'radio',
|
||||||
|
'value': 'edit',
|
||||||
|
}).on('change', updateMode);
|
||||||
|
|
||||||
|
this.modeMarkdown = this.dom.el('input').attrs({
|
||||||
|
'name': 'export-mode',
|
||||||
|
'type': 'radio',
|
||||||
|
'value': 'markdown',
|
||||||
|
}).on('change', updateMode);
|
||||||
|
|
||||||
this.urlWidth = this.dom.el('input').attrs({
|
this.urlWidth = this.dom.el('input').attrs({
|
||||||
'min': 0,
|
'min': 0,
|
||||||
'placeholder': 'auto',
|
'placeholder': 'auto',
|
||||||
|
@ -1396,12 +1457,21 @@
|
||||||
this._refreshURL();
|
this._refreshURL();
|
||||||
});
|
});
|
||||||
|
|
||||||
const urlOpts = this.dom.el('div').setClass('config').add(
|
this.renderOpts = this.dom.el('div').add(
|
||||||
this.dom.el('label').add('width ', this.urlWidth),
|
this.dom.el('label').add('width ', this.urlWidth),
|
||||||
', ',
|
', ',
|
||||||
this.dom.el('label').add('height ', this.urlHeight),
|
this.dom.el('label').add('height ', this.urlHeight),
|
||||||
this.dom.el('span').setClass('or').add('or'),
|
this.dom.el('span').setClass('or').add('or'),
|
||||||
this.dom.el('label').add('zoom ', this.urlZoom),
|
this.dom.el('label').add('zoom ', this.urlZoom)
|
||||||
|
);
|
||||||
|
|
||||||
|
const urlOpts = this.dom.el('div').setClass('config').add(
|
||||||
|
this.dom.el('div').setClass('export-mode').add(
|
||||||
|
this.dom.el('label').add(this.modeRender, 'View'),
|
||||||
|
this.dom.el('label').add(this.modeEdit, 'Edit'),
|
||||||
|
this.dom.el('label').add(this.modeMarkdown, 'Markdown')
|
||||||
|
),
|
||||||
|
this.renderOpts,
|
||||||
this.urlOutput,
|
this.urlOutput,
|
||||||
copy,
|
copy,
|
||||||
copied
|
copied
|
||||||
|
@ -1414,7 +1484,10 @@
|
||||||
.add('Loading\u2026')
|
.add('Loading\u2026')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const ownURL = (typeof window === 'undefined') ? 'http://localhost' : window.location.href;
|
||||||
this.renderService = new URLExporter();
|
this.renderService = new URLExporter();
|
||||||
|
this.renderService.setEditBase(new URL('.', ownURL).href);
|
||||||
|
|
||||||
const relativePath = 'render/';
|
const relativePath = 'render/';
|
||||||
fetchResource(relativePath)
|
fetchResource(relativePath)
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
|
@ -1423,9 +1496,7 @@
|
||||||
if(!path || path.startsWith('<')) {
|
if(!path || path.startsWith('<')) {
|
||||||
path = relativePath;
|
path = relativePath;
|
||||||
}
|
}
|
||||||
this.renderService.setBase(
|
this.renderService.setRenderBase(new URL(path, ownURL).href);
|
||||||
new URL(path, window.location.href).href
|
|
||||||
);
|
|
||||||
urlBuilder.empty().add(urlOpts);
|
urlBuilder.empty().add(urlOpts);
|
||||||
this._refreshURL();
|
this._refreshURL();
|
||||||
})
|
})
|
||||||
|
@ -1440,11 +1511,27 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
_refreshURL() {
|
_refreshURL() {
|
||||||
this.urlOutput.val(this.renderService.getURL(this.code.value(), {
|
const code = this.code.value();
|
||||||
|
const viewOpts = {
|
||||||
height: Number.parseFloat(this.urlHeight.element.value),
|
height: Number.parseFloat(this.urlHeight.element.value),
|
||||||
width: Number.parseFloat(this.urlWidth.element.value),
|
width: Number.parseFloat(this.urlWidth.element.value),
|
||||||
zoom: Number.parseFloat(this.urlZoom.element.value || '1'),
|
zoom: Number.parseFloat(this.urlZoom.element.value || '1'),
|
||||||
}));
|
};
|
||||||
|
|
||||||
|
let url = '';
|
||||||
|
if(this.modeMarkdown.element.checked) {
|
||||||
|
const edit = this.renderService.getEditURL(code);
|
||||||
|
const view = this.renderService.getRenderURL(code, viewOpts);
|
||||||
|
const title = this.diagram.getTitle()
|
||||||
|
.replace(/[^a-zA-Z0-9 \-_'"]/g, '')
|
||||||
|
.trim();
|
||||||
|
url = `[](${edit})`;
|
||||||
|
} else if(this.modeEdit.element.checked) {
|
||||||
|
url = this.renderService.getEditURL(code);
|
||||||
|
} else {
|
||||||
|
url = this.renderService.getRenderURL(code, viewOpts);
|
||||||
|
}
|
||||||
|
this.urlOutput.val(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
_showURLBuilder() {
|
_showURLBuilder() {
|
||||||
|
@ -2214,6 +2301,32 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadHashDocument(hashNav, slotStorage) {
|
||||||
|
const editPrefix = 'edit:';
|
||||||
|
const hash = hashNav.getRawHash();
|
||||||
|
if(!hash.startsWith(editPrefix)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let doc = hash
|
||||||
|
.substr(editPrefix.length)
|
||||||
|
.split('/')
|
||||||
|
.map(decodeURIComponent)
|
||||||
|
.join('\n');
|
||||||
|
|
||||||
|
if(!doc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!doc.endsWith('\n')) {
|
||||||
|
doc += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
const newSlot = slotStorage.nextAvailableSlot();
|
||||||
|
slotStorage.set(newSlot, doc);
|
||||||
|
hashNav.setSlot(newSlot);
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
const loader = window.document.getElementById('loader');
|
const loader = window.document.getElementById('loader');
|
||||||
const [nav] = loader.getElementsByTagName('nav');
|
const [nav] = loader.getElementsByTagName('nav');
|
||||||
|
@ -2235,6 +2348,7 @@
|
||||||
// If the slot is changed by the user, reload to force a document load
|
// If the slot is changed by the user, reload to force a document load
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
|
loadHashDocument(hashNav, slotStorage);
|
||||||
|
|
||||||
loader.parentNode.removeChild(loader);
|
loader.parentNode.removeChild(loader);
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -37,6 +37,32 @@ function migrateOldDocument(slotStorage) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadHashDocument(hashNav, slotStorage) {
|
||||||
|
const editPrefix = 'edit:';
|
||||||
|
const hash = hashNav.getRawHash();
|
||||||
|
if(!hash.startsWith(editPrefix)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let doc = hash
|
||||||
|
.substr(editPrefix.length)
|
||||||
|
.split('/')
|
||||||
|
.map(decodeURIComponent)
|
||||||
|
.join('\n');
|
||||||
|
|
||||||
|
if(!doc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!doc.endsWith('\n')) {
|
||||||
|
doc += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
const newSlot = slotStorage.nextAvailableSlot();
|
||||||
|
slotStorage.set(newSlot, doc);
|
||||||
|
hashNav.setSlot(newSlot);
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
const loader = window.document.getElementById('loader');
|
const loader = window.document.getElementById('loader');
|
||||||
const [nav] = loader.getElementsByTagName('nav');
|
const [nav] = loader.getElementsByTagName('nav');
|
||||||
|
@ -58,6 +84,7 @@ window.addEventListener('load', () => {
|
||||||
// If the slot is changed by the user, reload to force a document load
|
// If the slot is changed by the user, reload to force a document load
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
|
loadHashDocument(hashNav, slotStorage);
|
||||||
|
|
||||||
loader.parentNode.removeChild(loader);
|
loader.parentNode.removeChild(loader);
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,14 @@ function fetchResource(path) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setDocumentTitle(diagramTitle) {
|
||||||
|
let title = diagramTitle.trim();
|
||||||
|
if(title.length > 20) {
|
||||||
|
title = title.substr(0, 18).trim() + '\u2026';
|
||||||
|
}
|
||||||
|
document.title = (title ? `${title} \u2014 ` : '') + 'Sequence Diagram';
|
||||||
|
}
|
||||||
|
|
||||||
export default class Interface {
|
export default class Interface {
|
||||||
constructor({
|
constructor({
|
||||||
sequenceDiagram,
|
sequenceDiagram,
|
||||||
|
@ -75,6 +83,7 @@ export default class Interface {
|
||||||
this.diagram
|
this.diagram
|
||||||
.on('render', () => {
|
.on('render', () => {
|
||||||
this.updateMinSize(this.diagram.getSize());
|
this.updateMinSize(this.diagram.getSize());
|
||||||
|
setDocumentTitle(this.diagram.getTitle());
|
||||||
this.pngDirty = true;
|
this.pngDirty = true;
|
||||||
})
|
})
|
||||||
.on('mouseover', (element) => this.code.markLineHover(element.ln))
|
.on('mouseover', (element) => this.code.markLineHover(element.ln))
|
||||||
|
@ -127,6 +136,32 @@ export default class Interface {
|
||||||
setTimeout(() => copied.styles({'display': 'none'}), 1500);
|
setTimeout(() => copied.styles({'display': 'none'}), 1500);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updateMode = () => {
|
||||||
|
this.renderOpts.styles({
|
||||||
|
'display': this.modeEdit.element.checked ? 'none' : 'block',
|
||||||
|
});
|
||||||
|
this._refreshURL();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.modeRender = this.dom.el('input').attrs({
|
||||||
|
'checked': 'checked',
|
||||||
|
'name': 'export-mode',
|
||||||
|
'type': 'radio',
|
||||||
|
'value': 'render',
|
||||||
|
}).on('change', updateMode);
|
||||||
|
|
||||||
|
this.modeEdit = this.dom.el('input').attrs({
|
||||||
|
'name': 'export-mode',
|
||||||
|
'type': 'radio',
|
||||||
|
'value': 'edit',
|
||||||
|
}).on('change', updateMode);
|
||||||
|
|
||||||
|
this.modeMarkdown = this.dom.el('input').attrs({
|
||||||
|
'name': 'export-mode',
|
||||||
|
'type': 'radio',
|
||||||
|
'value': 'markdown',
|
||||||
|
}).on('change', updateMode);
|
||||||
|
|
||||||
this.urlWidth = this.dom.el('input').attrs({
|
this.urlWidth = this.dom.el('input').attrs({
|
||||||
'min': 0,
|
'min': 0,
|
||||||
'placeholder': 'auto',
|
'placeholder': 'auto',
|
||||||
|
@ -158,12 +193,21 @@ export default class Interface {
|
||||||
this._refreshURL();
|
this._refreshURL();
|
||||||
});
|
});
|
||||||
|
|
||||||
const urlOpts = this.dom.el('div').setClass('config').add(
|
this.renderOpts = this.dom.el('div').add(
|
||||||
this.dom.el('label').add('width ', this.urlWidth),
|
this.dom.el('label').add('width ', this.urlWidth),
|
||||||
', ',
|
', ',
|
||||||
this.dom.el('label').add('height ', this.urlHeight),
|
this.dom.el('label').add('height ', this.urlHeight),
|
||||||
this.dom.el('span').setClass('or').add('or'),
|
this.dom.el('span').setClass('or').add('or'),
|
||||||
this.dom.el('label').add('zoom ', this.urlZoom),
|
this.dom.el('label').add('zoom ', this.urlZoom)
|
||||||
|
);
|
||||||
|
|
||||||
|
const urlOpts = this.dom.el('div').setClass('config').add(
|
||||||
|
this.dom.el('div').setClass('export-mode').add(
|
||||||
|
this.dom.el('label').add(this.modeRender, 'View'),
|
||||||
|
this.dom.el('label').add(this.modeEdit, 'Edit'),
|
||||||
|
this.dom.el('label').add(this.modeMarkdown, 'Markdown')
|
||||||
|
),
|
||||||
|
this.renderOpts,
|
||||||
this.urlOutput,
|
this.urlOutput,
|
||||||
copy,
|
copy,
|
||||||
copied
|
copied
|
||||||
|
@ -176,7 +220,10 @@ export default class Interface {
|
||||||
.add('Loading\u2026')
|
.add('Loading\u2026')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const ownURL = (typeof window === 'undefined') ? 'http://localhost' : window.location.href;
|
||||||
this.renderService = new URLExporter();
|
this.renderService = new URLExporter();
|
||||||
|
this.renderService.setEditBase(new URL('.', ownURL).href);
|
||||||
|
|
||||||
const relativePath = 'render/';
|
const relativePath = 'render/';
|
||||||
fetchResource(relativePath)
|
fetchResource(relativePath)
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
|
@ -185,9 +232,7 @@ export default class Interface {
|
||||||
if(!path || path.startsWith('<')) {
|
if(!path || path.startsWith('<')) {
|
||||||
path = relativePath;
|
path = relativePath;
|
||||||
}
|
}
|
||||||
this.renderService.setBase(
|
this.renderService.setRenderBase(new URL(path, ownURL).href);
|
||||||
new URL(path, window.location.href).href
|
|
||||||
);
|
|
||||||
urlBuilder.empty().add(urlOpts);
|
urlBuilder.empty().add(urlOpts);
|
||||||
this._refreshURL();
|
this._refreshURL();
|
||||||
})
|
})
|
||||||
|
@ -202,11 +247,27 @@ export default class Interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
_refreshURL() {
|
_refreshURL() {
|
||||||
this.urlOutput.val(this.renderService.getURL(this.code.value(), {
|
const code = this.code.value();
|
||||||
|
const viewOpts = {
|
||||||
height: Number.parseFloat(this.urlHeight.element.value),
|
height: Number.parseFloat(this.urlHeight.element.value),
|
||||||
width: Number.parseFloat(this.urlWidth.element.value),
|
width: Number.parseFloat(this.urlWidth.element.value),
|
||||||
zoom: Number.parseFloat(this.urlZoom.element.value || '1'),
|
zoom: Number.parseFloat(this.urlZoom.element.value || '1'),
|
||||||
}));
|
};
|
||||||
|
|
||||||
|
let url = '';
|
||||||
|
if(this.modeMarkdown.element.checked) {
|
||||||
|
const edit = this.renderService.getEditURL(code);
|
||||||
|
const view = this.renderService.getRenderURL(code, viewOpts);
|
||||||
|
const title = this.diagram.getTitle()
|
||||||
|
.replace(/[^a-zA-Z0-9 \-_'"]/g, '')
|
||||||
|
.trim();
|
||||||
|
url = `[](${edit})`;
|
||||||
|
} else if(this.modeEdit.element.checked) {
|
||||||
|
url = this.renderService.getEditURL(code);
|
||||||
|
} else {
|
||||||
|
url = this.renderService.getRenderURL(code, viewOpts);
|
||||||
|
}
|
||||||
|
this.urlOutput.val(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
_showURLBuilder() {
|
_showURLBuilder() {
|
||||||
|
|
|
@ -12,20 +12,34 @@ function valid(v = null) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class URLExporter {
|
export default class URLExporter {
|
||||||
constructor(base = '') {
|
constructor(renderBase = '', editBase = '') {
|
||||||
this.base = base;
|
this.renderBase = renderBase;
|
||||||
|
this.editBase = editBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
setBase(base) {
|
setRenderBase(renderBase) {
|
||||||
this.base = base;
|
this.renderBase = renderBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
_convertCode(code) {
|
setEditBase(editBase) {
|
||||||
return code
|
this.editBase = editBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
_convertCode(code, keepBlankLines = false) {
|
||||||
|
let lines = code
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.map(encodeURIComponent)
|
.map(encodeURIComponent);
|
||||||
.filter((ln) => ln !== '')
|
|
||||||
.join('/');
|
if(keepBlankLines) {
|
||||||
|
// Always trim trailing blank lines
|
||||||
|
while(lines.length > 0 && lines[lines.length - 1] === '') {
|
||||||
|
-- lines.length;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lines = lines.filter((ln) => ln !== '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines.join('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
_convertWidthHeight(width, height) {
|
_convertWidthHeight(width, height) {
|
||||||
|
@ -56,12 +70,20 @@ export default class URLExporter {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
getURL(code, size = {}) {
|
getRenderURL(code, size = {}) {
|
||||||
return (
|
return (
|
||||||
this.base +
|
this.renderBase +
|
||||||
this._convertSize(size) +
|
this._convertSize(size) +
|
||||||
this._convertCode(code) +
|
this._convertCode(code) +
|
||||||
'.svg'
|
'.svg'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getEditURL(code) {
|
||||||
|
return (
|
||||||
|
this.editBase +
|
||||||
|
'#edit:' +
|
||||||
|
this._convertCode(code, true)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,70 +3,74 @@ import URLExporter from './URLExporter.mjs';
|
||||||
describe('URLExporter', () => {
|
describe('URLExporter', () => {
|
||||||
it('converts code into a URL-safe format', () => {
|
it('converts code into a URL-safe format', () => {
|
||||||
const exporter = new URLExporter();
|
const exporter = new URLExporter();
|
||||||
const url = exporter.getURL('A\nB');
|
const url = exporter.getRenderURL('A\nB');
|
||||||
|
|
||||||
expect(url).toEqual('A/B.svg');
|
expect(url).toEqual('A/B.svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('escapes special characters', () => {
|
it('escapes special characters', () => {
|
||||||
const exporter = new URLExporter();
|
const exporter = new URLExporter();
|
||||||
const url = exporter.getURL('a/b%c"d');
|
const url = exporter.getRenderURL('a/b%c"d');
|
||||||
|
|
||||||
expect(url).toEqual('a%2Fb%25c%22d.svg');
|
expect(url).toEqual('a%2Fb%25c%22d.svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adds a base url if specified', () => {
|
it('adds a base url if specified', () => {
|
||||||
const exporter = new URLExporter('abc/');
|
const exporter = new URLExporter('abc/');
|
||||||
const url = exporter.getURL('d');
|
const url = exporter.getRenderURL('d');
|
||||||
|
|
||||||
expect(url).toEqual('abc/d.svg');
|
expect(url).toEqual('abc/d.svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adds width/height information if specified', () => {
|
it('adds width/height information if specified', () => {
|
||||||
const exporter = new URLExporter();
|
const exporter = new URLExporter();
|
||||||
const url = exporter.getURL('a', {height: 20, width: 10});
|
const url = exporter.getRenderURL('a', {height: 20, width: 10});
|
||||||
|
|
||||||
expect(url).toEqual('w10h20/a.svg');
|
expect(url).toEqual('w10h20/a.svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adds zoom information if specified', () => {
|
it('adds zoom information if specified', () => {
|
||||||
const exporter = new URLExporter();
|
const exporter = new URLExporter();
|
||||||
const url = exporter.getURL('a', {zoom: 2});
|
const url = exporter.getRenderURL('a', {zoom: 2});
|
||||||
|
|
||||||
expect(url).toEqual('z2/a.svg');
|
expect(url).toEqual('z2/a.svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('ignores zoom of 1', () => {
|
it('ignores zoom of 1', () => {
|
||||||
const exporter = new URLExporter();
|
const exporter = new URLExporter();
|
||||||
const url = exporter.getURL('a', {zoom: 1});
|
const url = exporter.getRenderURL('a', {zoom: 1});
|
||||||
|
|
||||||
expect(url).toEqual('a.svg');
|
expect(url).toEqual('a.svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('ignores values of not-a-number', () => {
|
it('ignores values of not-a-number', () => {
|
||||||
const exporter = new URLExporter();
|
const exporter = new URLExporter();
|
||||||
const url = exporter.getURL('a', {zoom: Number.NaN});
|
const url = exporter.getRenderURL('a', {zoom: Number.NaN});
|
||||||
|
|
||||||
expect(url).toEqual('a.svg');
|
expect(url).toEqual('a.svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adds just width if specified', () => {
|
it('adds just width if specified', () => {
|
||||||
const exporter = new URLExporter();
|
const exporter = new URLExporter();
|
||||||
const url = exporter.getURL('a', {width: 10});
|
const url = exporter.getRenderURL('a', {width: 10});
|
||||||
|
|
||||||
expect(url).toEqual('w10/a.svg');
|
expect(url).toEqual('w10/a.svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adds just height if specified', () => {
|
it('adds just height if specified', () => {
|
||||||
const exporter = new URLExporter();
|
const exporter = new URLExporter();
|
||||||
const url = exporter.getURL('a', {height: 10});
|
const url = exporter.getRenderURL('a', {height: 10});
|
||||||
|
|
||||||
expect(url).toEqual('h10/a.svg');
|
expect(url).toEqual('h10/a.svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('prefers width/height over zoom', () => {
|
it('prefers width/height over zoom', () => {
|
||||||
const exporter = new URLExporter();
|
const exporter = new URLExporter();
|
||||||
const url = exporter.getURL('a', {height: 20, width: 10, zoom: 2});
|
const url = exporter.getRenderURL('a', {
|
||||||
|
height: 20,
|
||||||
|
width: 10,
|
||||||
|
zoom: 2,
|
||||||
|
});
|
||||||
|
|
||||||
expect(url).toEqual('w10h20/a.svg');
|
expect(url).toEqual('w10h20/a.svg');
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,6 +16,10 @@ export default class HashSlotNav {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getRawHash() {
|
||||||
|
return getHash();
|
||||||
|
}
|
||||||
|
|
||||||
maxSlots() {
|
maxSlots() {
|
||||||
// Capacity of localStorage is limited
|
// Capacity of localStorage is limited
|
||||||
// So avoid allowing too many documents
|
// So avoid allowing too many documents
|
||||||
|
|
|
@ -315,7 +315,16 @@ html, body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.urlbuilder .config {
|
.urlbuilder .config {
|
||||||
padding-top: 10px;
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.urlbuilder .export-mode input {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.urlbuilder .export-mode label {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 10px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.urlbuilder input[type=number] {
|
.urlbuilder input[type=number] {
|
||||||
|
@ -325,7 +334,7 @@ html, body {
|
||||||
|
|
||||||
.urlbuilder .or {
|
.urlbuilder .or {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 10px 0;
|
margin: 5px 0;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue