kopia lustrzana https://github.com/deathbeds/ipydrawio
add export
rodzic
f0b6826012
commit
3674c341ff
|
@ -38,7 +38,7 @@ const DRAWIO_URL = URLExt.join(
|
|||
"node_modules/jupyterlab-drawio/src/drawio/src/main/webapp/index.html"
|
||||
);
|
||||
|
||||
const DEBUG = 1;
|
||||
const DEBUG = 0;
|
||||
|
||||
/**
|
||||
* Core URL params that are required to function properly
|
||||
|
@ -112,6 +112,14 @@ export class DrawioWidget extends DocumentWidget<IFrame> {
|
|||
await import("./_static");
|
||||
}
|
||||
|
||||
exportAs(format: string) {
|
||||
this._exportPromise = new PromiseDelegate();
|
||||
|
||||
this.postMessage({ action: "export", format });
|
||||
|
||||
return this._exportPromise.promise;
|
||||
}
|
||||
|
||||
handleMessageEvent(evt: MessageEvent) {
|
||||
const msg = JSON.parse(evt.data);
|
||||
if (this._frame == null || evt.source !== this._frame.contentWindow) {
|
||||
|
@ -139,6 +147,10 @@ export class DrawioWidget extends DocumentWidget<IFrame> {
|
|||
this._lastEmitted = msg.xml;
|
||||
this.context.model.fromString(msg.xml);
|
||||
break;
|
||||
case "export":
|
||||
this._exportPromise.resolve(msg.data);
|
||||
this._exportPromise = null;
|
||||
break;
|
||||
default:
|
||||
DEBUG && console.warn("unhandled message", msg.event, msg);
|
||||
break;
|
||||
|
@ -164,13 +176,13 @@ export class DrawioWidget extends DocumentWidget<IFrame> {
|
|||
this._frame.contentWindow.postMessage(JSON.stringify(msg), "*");
|
||||
}
|
||||
|
||||
drawioTheme() {
|
||||
private drawioTheme() {
|
||||
return document.querySelector('body[data-jp-theme-light="true"]')
|
||||
? "kennedy"
|
||||
: "dark";
|
||||
}
|
||||
|
||||
drawioUrl() {
|
||||
private drawioUrl() {
|
||||
const query = new URLSearchParams();
|
||||
const params = {
|
||||
...DEFAULT_EMBED_PARAMS,
|
||||
|
@ -237,6 +249,7 @@ export class DrawioWidget extends DocumentWidget<IFrame> {
|
|||
public revealed: Promise<void>;
|
||||
readonly context: DocumentRegistry.Context;
|
||||
private _ready = new PromiseDelegate<void>();
|
||||
private _exportPromise: PromiseDelegate<string>;
|
||||
private _frame: HTMLIFrameElement;
|
||||
private _lastEmitted: string;
|
||||
}
|
||||
|
|
243
src/index.ts
243
src/index.ts
|
@ -13,129 +13,256 @@
|
|||
// limitations under the License.
|
||||
|
||||
import {
|
||||
ILayoutRestorer, JupyterLab, JupyterFrontEndPlugin
|
||||
} from '@jupyterlab/application';
|
||||
ILayoutRestorer,
|
||||
JupyterLab,
|
||||
JupyterFrontEndPlugin,
|
||||
} from "@jupyterlab/application";
|
||||
|
||||
import {
|
||||
WidgetTracker, IWidgetTracker
|
||||
} from '@jupyterlab/apputils';
|
||||
WidgetTracker,
|
||||
IWidgetTracker,
|
||||
ICommandPalette,
|
||||
} from "@jupyterlab/apputils";
|
||||
|
||||
import {
|
||||
IFileBrowserFactory
|
||||
} from '@jupyterlab/filebrowser';
|
||||
import { IFileBrowserFactory } from "@jupyterlab/filebrowser";
|
||||
|
||||
import {
|
||||
ILauncher
|
||||
} from '@jupyterlab/launcher';
|
||||
import { Contents } from "@jupyterlab/services";
|
||||
|
||||
import {
|
||||
IMainMenu
|
||||
} from '@jupyterlab/mainmenu';
|
||||
import { ILauncher } from "@jupyterlab/launcher";
|
||||
|
||||
import {
|
||||
Token
|
||||
} from '@lumino/coreutils';
|
||||
import { IMainMenu } from "@jupyterlab/mainmenu";
|
||||
|
||||
import {
|
||||
DrawioWidget, DrawioFactory
|
||||
} from './editor';
|
||||
import { Token } from "@lumino/coreutils";
|
||||
|
||||
import { DrawioWidget, DrawioFactory } from "./editor";
|
||||
import { PathExt } from "@jupyterlab/coreutils";
|
||||
|
||||
/**
|
||||
* The name of the factory that creates editor widgets.
|
||||
*/
|
||||
const FACTORY = 'Drawio';
|
||||
const FACTORY = "Drawio";
|
||||
|
||||
/**
|
||||
* Supported formats include
|
||||
* html (old embed format),
|
||||
* html2 (new embed format),
|
||||
* svg (default),
|
||||
* xmlsvg (SVG with embeddded XML),
|
||||
* png and xmlpng (PNG with embedded XML).
|
||||
* The data parameter in the exportevent contains a valid data URI for the given export format.
|
||||
*/
|
||||
|
||||
interface IExportFormat {
|
||||
key: string;
|
||||
ext: string;
|
||||
label: string;
|
||||
format: Contents.FileFormat;
|
||||
mimetype: string;
|
||||
transform?: (raw: string) => string;
|
||||
}
|
||||
|
||||
const stripDataURI = (raw: string) => raw.split(",")[1];
|
||||
const unbase64SVG = (raw: string) => atob(stripDataURI(raw));
|
||||
|
||||
const EXPORT_FORMATS: IExportFormat[] = [
|
||||
{
|
||||
key: "svg",
|
||||
label: "SVG",
|
||||
ext: ".svg",
|
||||
format: "text",
|
||||
mimetype: "image/svg+xml",
|
||||
transform: unbase64SVG,
|
||||
},
|
||||
{
|
||||
key: "xmlsvg",
|
||||
label: "SVG (Editable)",
|
||||
ext: ".svg",
|
||||
format: "text",
|
||||
mimetype: "image/svg+xml",
|
||||
transform: unbase64SVG,
|
||||
},
|
||||
{
|
||||
key: "html2",
|
||||
label: "HTML",
|
||||
ext: ".html",
|
||||
format: "text",
|
||||
mimetype: "text/html",
|
||||
},
|
||||
{
|
||||
key: "png",
|
||||
label: "PNG",
|
||||
ext: ".png",
|
||||
format: "base64",
|
||||
mimetype: "image/png",
|
||||
transform: stripDataURI,
|
||||
},
|
||||
{
|
||||
key: "xmlpng",
|
||||
label: "PNG (Editable)",
|
||||
ext: ".png",
|
||||
format: "base64",
|
||||
mimetype: "image/png",
|
||||
transform: stripDataURI,
|
||||
},
|
||||
];
|
||||
|
||||
interface IDrawioTracker extends IWidgetTracker<DrawioWidget> {}
|
||||
|
||||
export
|
||||
const IDrawioTracker = new Token<IDrawioTracker>('drawio/tracki');
|
||||
export const IDrawioTracker = new Token<IDrawioTracker>("drawio/tracki");
|
||||
|
||||
/**
|
||||
* The editor tracker extension.
|
||||
*/
|
||||
const plugin: JupyterFrontEndPlugin<IDrawioTracker> = {
|
||||
activate,
|
||||
id: '@jupyterlab/drawio-extension:plugin',
|
||||
requires: [IFileBrowserFactory, ILayoutRestorer, IMainMenu],
|
||||
id: "@jupyterlab/drawio-extension:plugin",
|
||||
requires: [IFileBrowserFactory, ILayoutRestorer, IMainMenu, ICommandPalette],
|
||||
optional: [ILauncher],
|
||||
provides: IDrawioTracker,
|
||||
autoStart: true
|
||||
autoStart: true,
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
|
||||
function activate(app: JupyterLab,
|
||||
browserFactory: IFileBrowserFactory,
|
||||
restorer: ILayoutRestorer,
|
||||
menu: IMainMenu,
|
||||
launcher: ILauncher | null
|
||||
): IDrawioTracker {
|
||||
const namespace = 'drawio';
|
||||
const factory = new DrawioFactory({ name: FACTORY, fileTypes: ['dio'], defaultFor: ['dio'] });
|
||||
function activate(
|
||||
app: JupyterLab,
|
||||
browserFactory: IFileBrowserFactory,
|
||||
restorer: ILayoutRestorer,
|
||||
menu: IMainMenu,
|
||||
palette: ICommandPalette,
|
||||
launcher: ILauncher | null
|
||||
): IDrawioTracker {
|
||||
const namespace = "drawio";
|
||||
const factory = new DrawioFactory({
|
||||
name: FACTORY,
|
||||
fileTypes: ["dio"],
|
||||
defaultFor: ["dio"],
|
||||
});
|
||||
const { commands } = app;
|
||||
const tracker = new WidgetTracker<DrawioWidget>({ namespace });
|
||||
|
||||
/**
|
||||
* Whether there is an active DrawIO editor.
|
||||
*/
|
||||
function isEnabled(): boolean {
|
||||
return (
|
||||
tracker.currentWidget !== null &&
|
||||
tracker.currentWidget === app.shell.currentWidget
|
||||
);
|
||||
}
|
||||
|
||||
// Handle state restoration.
|
||||
restorer.restore(tracker, {
|
||||
command: 'docmanager:open',
|
||||
args: widget => ({ path: widget.context.path, factory: FACTORY }),
|
||||
name: widget => widget.context.path
|
||||
command: "docmanager:open",
|
||||
args: (widget) => ({ path: widget.context.path, factory: FACTORY }),
|
||||
name: (widget) => widget.context.path,
|
||||
});
|
||||
|
||||
factory.widgetCreated.connect((sender, widget) => {
|
||||
widget.title.icon = 'jp-MaterialIcon jp-ImageIcon'; // TODO change
|
||||
widget.title.icon = "jp-MaterialIcon jp-ImageIcon"; // TODO change
|
||||
|
||||
// Notify the instance tracker if restore data needs to update.
|
||||
widget.context.pathChanged.connect(() => { tracker.save(widget); });
|
||||
widget.context.pathChanged.connect(() => {
|
||||
tracker.save(widget);
|
||||
});
|
||||
tracker.add(widget);
|
||||
});
|
||||
app.docRegistry.addWidgetFactory(factory);
|
||||
|
||||
// register the filetype
|
||||
app.docRegistry.addFileType({
|
||||
name: 'dio',
|
||||
displayName: 'Diagram',
|
||||
mimeTypes: ['application/dio'],
|
||||
extensions: ['.dio'],
|
||||
iconClass: 'jp-MaterialIcon jp-ImageIcon',
|
||||
fileFormat: 'text'
|
||||
name: "dio",
|
||||
displayName: "Diagram",
|
||||
mimeTypes: ["application/dio"],
|
||||
extensions: [".dio"],
|
||||
iconClass: "jp-MaterialIcon jp-ImageIcon",
|
||||
fileFormat: "text",
|
||||
});
|
||||
|
||||
// Function to create a new untitled diagram file, given
|
||||
// the current working directory.
|
||||
const createNewDIO = (cwd: string) => {
|
||||
return commands.execute('docmanager:new-untitled', {
|
||||
path: cwd, type: 'file', ext: '.dio'
|
||||
}).then(model => {
|
||||
return commands.execute('docmanager:open', {
|
||||
path: model.path, factory: FACTORY
|
||||
return commands
|
||||
.execute("docmanager:new-untitled", {
|
||||
path: cwd,
|
||||
type: "file",
|
||||
ext: ".dio",
|
||||
})
|
||||
.then((model: Contents.IModel) => {
|
||||
return commands.execute("docmanager:open", {
|
||||
path: model.path,
|
||||
factory: FACTORY,
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
EXPORT_FORMATS.map((exportFormat) => {
|
||||
const { ext, key, format, label, mimetype } = exportFormat;
|
||||
const transform = exportFormat.transform || String;
|
||||
const _exporter = async (cwd: string) => {
|
||||
let model: Contents.IModel = await commands.execute(
|
||||
"docmanager:new-untitled",
|
||||
{
|
||||
path: cwd,
|
||||
type: "file",
|
||||
ext,
|
||||
}
|
||||
);
|
||||
let drawio = app.shell.currentWidget as DrawioWidget;
|
||||
let stem = PathExt.basename(drawio.context.path);
|
||||
model = await app.serviceManager.contents.rename(
|
||||
model.path,
|
||||
PathExt.join(cwd, `${stem}${ext}`)
|
||||
);
|
||||
|
||||
const rawContent = await drawio.exportAs(key);
|
||||
|
||||
await app.serviceManager.contents.save(model.path, {
|
||||
...model,
|
||||
format,
|
||||
mimetype,
|
||||
content: transform(rawContent),
|
||||
});
|
||||
};
|
||||
|
||||
commands.addCommand(`drawio:export-${key}`, {
|
||||
label: `Export diagram as ${label}`,
|
||||
execute: () => {
|
||||
let cwd = browserFactory.defaultBrowser.model.path;
|
||||
return _exporter(cwd);
|
||||
},
|
||||
isEnabled,
|
||||
});
|
||||
|
||||
palette.addItem({
|
||||
command: `drawio:export-${key}`,
|
||||
category: "Diagram Export",
|
||||
});
|
||||
});
|
||||
|
||||
// Add a command for creating a new diagram file.
|
||||
commands.addCommand('drawio:create-new', {
|
||||
label: 'Diagram',
|
||||
iconClass: 'jp-MaterialIcon jp-ImageIcon',
|
||||
caption: 'Create a new diagram file',
|
||||
commands.addCommand("drawio:create-new", {
|
||||
label: "Diagram",
|
||||
iconClass: "jp-MaterialIcon jp-ImageIcon",
|
||||
caption: "Create a new diagram file",
|
||||
execute: () => {
|
||||
let cwd = browserFactory.defaultBrowser.model.path;
|
||||
return createNewDIO(cwd);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Add a launcher item if the launcher is available.
|
||||
if (launcher) {
|
||||
launcher.add({
|
||||
command: 'drawio:create-new',
|
||||
command: "drawio:create-new",
|
||||
rank: 1,
|
||||
category: 'Other'
|
||||
category: "Other",
|
||||
});
|
||||
}
|
||||
|
||||
if (menu) {
|
||||
// Add new text file creation to the file menu.
|
||||
menu.fileMenu.newMenu.addGroup([{ command: 'drawio:create-new' }], 40);
|
||||
menu.fileMenu.newMenu.addGroup([{ command: "drawio:create-new" }], 40);
|
||||
}
|
||||
|
||||
return tracker;
|
||||
|
|
Ładowanie…
Reference in New Issue