mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
unified export dialog, WIP
This commit is contained in:
parent
3e351bd8d3
commit
ee23bcc783
67
src/public/javascripts/dialogs/export.js
Normal file
67
src/public/javascripts/dialogs/export.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import treeService from '../services/tree.js';
|
||||||
|
import treeUtils from "../services/tree_utils.js";
|
||||||
|
import exportService from "../services/export.js";
|
||||||
|
|
||||||
|
const $dialog = $("#export-dialog");
|
||||||
|
const $form = $("#export-form");
|
||||||
|
const $noteTitle = $dialog.find(".note-title");
|
||||||
|
const $subtreeFormats = $("#export-subtree-formats");
|
||||||
|
const $singleFormats = $("#export-single-formats");
|
||||||
|
const $subtreeType = $("#export-type-subtree");
|
||||||
|
const $singleType = $("#export-type-single");
|
||||||
|
|
||||||
|
async function showDialog(defaultType) {
|
||||||
|
if (defaultType === 'subtree') {
|
||||||
|
$subtreeType.prop("checked", true).change();
|
||||||
|
}
|
||||||
|
else if (defaultType === 'single') {
|
||||||
|
$singleType.prop("checked", true).change();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error("Unrecognized type " + defaultType);
|
||||||
|
}
|
||||||
|
|
||||||
|
glob.activeDialog = $dialog;
|
||||||
|
|
||||||
|
$dialog.modal();
|
||||||
|
|
||||||
|
const currentNode = treeService.getCurrentNode();
|
||||||
|
const noteTitle = await treeUtils.getNoteTitle(currentNode.data.noteId);
|
||||||
|
|
||||||
|
$noteTitle.html(noteTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
$form.submit(() => {
|
||||||
|
const exportType = $dialog.find("input[name='export-type']:checked").val();
|
||||||
|
|
||||||
|
const currentNode = treeService.getCurrentNode();
|
||||||
|
|
||||||
|
exportService.exportNote(currentNode.data.branchId, exportType);
|
||||||
|
|
||||||
|
$dialog.modal('hide');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('input[name=export-type]').change(function () {
|
||||||
|
if (this.value === 'subtree') {
|
||||||
|
if ($("input[name=export-subtree-format]:checked").length === 0) {
|
||||||
|
$("input[name=export-subtree-format]:first").prop("checked", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$subtreeFormats.slideDown();
|
||||||
|
$singleFormats.slideUp();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($("input[name=export-single-format]:checked").length === 0) {
|
||||||
|
$("input[name=export-single-format]:first").prop("checked", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$subtreeFormats.slideUp();
|
||||||
|
$singleFormats.slideDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
showDialog
|
||||||
|
};
|
@ -1,35 +0,0 @@
|
|||||||
import treeService from '../services/tree.js';
|
|
||||||
import server from '../services/server.js';
|
|
||||||
import treeUtils from "../services/tree_utils.js";
|
|
||||||
import exportService from "../services/export.js";
|
|
||||||
|
|
||||||
const $dialog = $("#export-subtree-dialog");
|
|
||||||
const $form = $("#export-subtree-form");
|
|
||||||
const $noteTitle = $dialog.find(".note-title");
|
|
||||||
|
|
||||||
async function showDialog() {
|
|
||||||
glob.activeDialog = $dialog;
|
|
||||||
|
|
||||||
$dialog.modal();
|
|
||||||
|
|
||||||
const currentNode = treeService.getCurrentNode();
|
|
||||||
const noteTitle = await treeUtils.getNoteTitle(currentNode.data.noteId);
|
|
||||||
|
|
||||||
$noteTitle.html(noteTitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
$form.submit(() => {
|
|
||||||
const exportFormat = $dialog.find("input[name='export-format']:checked").val();
|
|
||||||
|
|
||||||
const currentNode = treeService.getCurrentNode();
|
|
||||||
|
|
||||||
exportService.exportSubtree(currentNode.data.branchId, exportFormat);
|
|
||||||
|
|
||||||
$dialog.modal('hide');
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
export default {
|
|
||||||
showDialog
|
|
||||||
};
|
|
5
src/public/javascripts/services/bootstrap.js
vendored
5
src/public/javascripts/services/bootstrap.js
vendored
@ -7,6 +7,7 @@ import recentChangesDialog from '../dialogs/recent_changes.js';
|
|||||||
import optionsDialog from '../dialogs/options.js';
|
import optionsDialog from '../dialogs/options.js';
|
||||||
import sqlConsoleDialog from '../dialogs/sql_console.js';
|
import sqlConsoleDialog from '../dialogs/sql_console.js';
|
||||||
import markdownImportDialog from '../dialogs/markdown_import.js';
|
import markdownImportDialog from '../dialogs/markdown_import.js';
|
||||||
|
import exportDialog from '../dialogs/export.js';
|
||||||
|
|
||||||
import cloning from './cloning.js';
|
import cloning from './cloning.js';
|
||||||
import contextMenu from './tree_context_menu.js';
|
import contextMenu from './tree_context_menu.js';
|
||||||
@ -103,12 +104,12 @@ if (utils.isElectron()) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#export-note-to-markdown-button").click(function () {
|
$("#export-note-button").click(function () {
|
||||||
if ($(this).hasClass("disabled")) {
|
if ($(this).hasClass("disabled")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
exportService.exportSubtree(noteDetailService.getCurrentNoteId(), 'markdown-single')
|
exportDialog.showDialog('single');
|
||||||
});
|
});
|
||||||
|
|
||||||
treeService.showTree();
|
treeService.showTree();
|
||||||
|
@ -4,7 +4,7 @@ import protectedSessionHolder from './protected_session_holder.js';
|
|||||||
import utils from './utils.js';
|
import utils from './utils.js';
|
||||||
import server from './server.js';
|
import server from './server.js';
|
||||||
|
|
||||||
function exportSubtree(noteId, format) {
|
function exportNote(noteId, format) {
|
||||||
const url = utils.getHost() + "/api/notes/" + noteId + "/export/" + format +
|
const url = utils.getHost() + "/api/notes/" + noteId + "/export/" + format +
|
||||||
"?protectedSessionId=" + encodeURIComponent(protectedSessionHolder.getProtectedSessionId());
|
"?protectedSessionId=" + encodeURIComponent(protectedSessionHolder.getProtectedSessionId());
|
||||||
|
|
||||||
@ -47,6 +47,6 @@ $("#import-upload").change(async function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
exportSubtree,
|
exportNote,
|
||||||
importIntoNote
|
importIntoNote
|
||||||
};
|
};
|
@ -564,8 +564,6 @@ async function createNote(node, parentNoteId, target, isProtected, saveSelection
|
|||||||
|
|
||||||
clearSelectedNodes(); // to unmark previously active node
|
clearSelectedNodes(); // to unmark previously active node
|
||||||
|
|
||||||
infoService.showMessage("Created!");
|
|
||||||
|
|
||||||
return {note, branch};
|
return {note, branch};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import protectedSessionService from './protected_session.js';
|
|||||||
import treeChangesService from './branches.js';
|
import treeChangesService from './branches.js';
|
||||||
import treeUtils from './tree_utils.js';
|
import treeUtils from './tree_utils.js';
|
||||||
import branchPrefixDialog from '../dialogs/branch_prefix.js';
|
import branchPrefixDialog from '../dialogs/branch_prefix.js';
|
||||||
import exportSubtreeDialog from '../dialogs/export_subtree.js';
|
import exportDialog from '../dialogs/export.js';
|
||||||
import infoService from "./info.js";
|
import infoService from "./info.js";
|
||||||
import treeCache from "./tree_cache.js";
|
import treeCache from "./tree_cache.js";
|
||||||
import syncService from "./sync.js";
|
import syncService from "./sync.js";
|
||||||
@ -93,7 +93,7 @@ const contextMenuItems = [
|
|||||||
{title: "Paste into <kbd>Ctrl+V</kbd>", cmd: "pasteInto", uiIcon: "clipboard"},
|
{title: "Paste into <kbd>Ctrl+V</kbd>", cmd: "pasteInto", uiIcon: "clipboard"},
|
||||||
{title: "Paste after", cmd: "pasteAfter", uiIcon: "clipboard"},
|
{title: "Paste after", cmd: "pasteAfter", uiIcon: "clipboard"},
|
||||||
{title: "----"},
|
{title: "----"},
|
||||||
{title: "Export subtree", cmd: "exportSubtree", uiIcon: "arrow-up-right"},
|
{title: "Export", cmd: "export", uiIcon: "arrow-up-right"},
|
||||||
{title: "Import into note (tar, opml, md, enex)", cmd: "importIntoNote", uiIcon: "arrow-down-left"},
|
{title: "Import into note (tar, opml, md, enex)", cmd: "importIntoNote", uiIcon: "arrow-down-left"},
|
||||||
{title: "----"},
|
{title: "----"},
|
||||||
{title: "Collapse subtree <kbd>Alt+-</kbd>", cmd: "collapseSubtree", uiIcon: "align-justify"},
|
{title: "Collapse subtree <kbd>Alt+-</kbd>", cmd: "collapseSubtree", uiIcon: "align-justify"},
|
||||||
@ -127,7 +127,7 @@ async function getContextMenuItems(event) {
|
|||||||
enableItem("pasteAfter", clipboardIds.length > 0 && isNotRoot && parentNote.type !== 'search');
|
enableItem("pasteAfter", clipboardIds.length > 0 && isNotRoot && parentNote.type !== 'search');
|
||||||
enableItem("pasteInto", clipboardIds.length > 0 && note.type !== 'search');
|
enableItem("pasteInto", clipboardIds.length > 0 && note.type !== 'search');
|
||||||
enableItem("importIntoNote", note.type !== 'search');
|
enableItem("importIntoNote", note.type !== 'search');
|
||||||
enableItem("exportSubtree", note.type !== 'search');
|
enableItem("export", note.type !== 'search');
|
||||||
enableItem("editBranchPrefix", isNotRoot && parentNote.type !== 'search');
|
enableItem("editBranchPrefix", isNotRoot && parentNote.type !== 'search');
|
||||||
|
|
||||||
// Activate node on right-click
|
// Activate node on right-click
|
||||||
@ -179,8 +179,8 @@ function selectContextMenuItem(event, cmd) {
|
|||||||
else if (cmd === "delete") {
|
else if (cmd === "delete") {
|
||||||
treeChangesService.deleteNodes(treeService.getSelectedNodes(true));
|
treeChangesService.deleteNodes(treeService.getSelectedNodes(true));
|
||||||
}
|
}
|
||||||
else if (cmd === "exportSubtree") {
|
else if (cmd === "export") {
|
||||||
exportSubtreeDialog.showDialog();
|
exportDialog.showDialog("subtree");
|
||||||
}
|
}
|
||||||
else if (cmd === "importIntoNote") {
|
else if (cmd === "importIntoNote") {
|
||||||
exportService.importIntoNote(node.data.noteId);
|
exportService.importIntoNote(node.data.noteId);
|
||||||
|
@ -685,3 +685,13 @@ div[data-notify="container"] {
|
|||||||
color: #777;
|
color: #777;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#export-form .form-check {
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#export-form .format-choice {
|
||||||
|
padding-left: 40px;
|
||||||
|
display: none;
|
||||||
|
}
|
@ -9,14 +9,15 @@ const repository = require("../../services/repository");
|
|||||||
async function exportNote(req, res) {
|
async function exportNote(req, res) {
|
||||||
// entityId maybe either noteId or branchId depending on format
|
// entityId maybe either noteId or branchId depending on format
|
||||||
const entityId = req.params.entityId;
|
const entityId = req.params.entityId;
|
||||||
|
const type = req.params.type;
|
||||||
const format = req.params.format;
|
const format = req.params.format;
|
||||||
|
|
||||||
if (format === 'native-tar') {
|
if (type === 'tar') {
|
||||||
await nativeTarExportService.exportToTar(await repository.getBranch(entityId), res);
|
await nativeTarExportService.exportToTar(await repository.getBranch(entityId), format, res);
|
||||||
}
|
|
||||||
else if (format === 'markdown-tar') {
|
|
||||||
await markdownTarExportService.exportToMarkdown(await repository.getBranch(entityId), res);
|
|
||||||
}
|
}
|
||||||
|
// else if (format === 'tar') {
|
||||||
|
// await markdownTarExportService.exportToMarkdown(await repository.getBranch(entityId), res);
|
||||||
|
// }
|
||||||
// export single note without subtree
|
// export single note without subtree
|
||||||
else if (format === 'markdown-single') {
|
else if (format === 'markdown-single') {
|
||||||
await markdownSingleExportService.exportSingleMarkdown(await repository.getNote(entityId), res);
|
await markdownSingleExportService.exportSingleMarkdown(await repository.getNote(entityId), res);
|
||||||
|
@ -3,8 +3,15 @@
|
|||||||
const html = require('html');
|
const html = require('html');
|
||||||
const native_tar = require('tar-stream');
|
const native_tar = require('tar-stream');
|
||||||
const sanitize = require("sanitize-filename");
|
const sanitize = require("sanitize-filename");
|
||||||
|
const mimeTypes = require('mime-types');
|
||||||
|
const TurndownService = require('turndown');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param format - 'html' or 'markdown'
|
||||||
|
*/
|
||||||
|
async function exportToTar(branch, format, res) {
|
||||||
|
const turndownService = new TurndownService();
|
||||||
|
|
||||||
async function exportToTar(branch, res) {
|
|
||||||
const pack = native_tar.pack();
|
const pack = native_tar.pack();
|
||||||
|
|
||||||
const exportedNoteIds = [];
|
const exportedNoteIds = [];
|
||||||
@ -52,6 +59,10 @@ async function exportToTar(branch, res) {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (note.type === 'text') {
|
||||||
|
metadata.format = format;
|
||||||
|
}
|
||||||
|
|
||||||
if (await note.hasLabel('excludeFromExport')) {
|
if (await note.hasLabel('excludeFromExport')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -75,9 +86,35 @@ async function exportToTar(branch, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function saveDataFile(childFileName, note) {
|
function saveDataFile(childFileName, note) {
|
||||||
const content = note.type === 'text' ? html.prettyPrint(note.content, {indent_size: 2}) : note.content;
|
let content = note.content;
|
||||||
|
|
||||||
pack.entry({name: childFileName + ".dat", size: content.length}, content);
|
if (note.type === 'text') {
|
||||||
|
if (format === 'html') {
|
||||||
|
content = html.prettyPrint(note.content, {indent_size: 2});
|
||||||
|
}
|
||||||
|
else if (format === 'markdown') {
|
||||||
|
content = turndownService.turndown(note.content);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error("Unknown format: " + format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const extension = mimeTypes.extension(note.mime)
|
||||||
|
|| getExceptionalExtension(note.mime)
|
||||||
|
|| "dat";
|
||||||
|
|
||||||
|
if (!childFileName.toLowerCase().endsWith(extension)) {
|
||||||
|
childFileName += "." + extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
pack.entry({name: childFileName, size: content.length}, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getExceptionalExtension(mime) {
|
||||||
|
if (mime === 'application/x-javascript') {
|
||||||
|
return 'js';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveMetadataFile(childFileName, metadata) {
|
function saveMetadataFile(childFileName, metadata) {
|
||||||
|
67
src/views/dialogs/export.ejs
Normal file
67
src/views/dialogs/export.ejs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<div id="export-dialog" class="modal fade mx-auto" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Export note</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<form id="export-form">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="export-type" id="export-type-subtree" value="subtree">
|
||||||
|
<label class="form-check-label" for="export-type-subtree">this note and all of its descendants</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="export-subtree-formats" class="format-choice">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="export-subtree-format" id="export-subtree-format-html"
|
||||||
|
value="html">
|
||||||
|
<label class="form-check-label" for="export-subtree-format-html">HTML in TAR archiv - this is recommended since this preserves all the formatting.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="export-subtree-format" id="export-subtree-format-markdown"
|
||||||
|
value="markdown-tar">
|
||||||
|
<label class="form-check-label" for="export-subtree-format-markdown">
|
||||||
|
Markdown - this preserves most of the formatting.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="export-subtree-format" id="export-subtree-format-opml"
|
||||||
|
value="opml">
|
||||||
|
<label class="form-check-label" for="export-subtree-format-opml">
|
||||||
|
OPML - outliner interchange format for text only. Formatting, images and files are not included.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="export-type" id="export-type-single" value="single">
|
||||||
|
<label class="form-check-label" for="export-type-single">only this note without its descendants</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="export-single-formats" class="format-choice">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="export-single-format" id="export-single-format-html" value="html">
|
||||||
|
<label class="form-check-label" for="export-single-format-html">HTML - this is recommended since this preserves all the formatting.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="export-single-format" id="export-single-format-markdown"
|
||||||
|
value="markdown-tar">
|
||||||
|
<label class="form-check-label" for="export-single-format-markdown">
|
||||||
|
Markdown - this preserves most of the formatting.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-primary btn-sm">Export</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -1,46 +0,0 @@
|
|||||||
<div id="export-subtree-dialog" class="modal fade mx-auto" tabindex="-1" role="dialog">
|
|
||||||
<div class="modal-dialog modal-lg" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title">Export subtree</h5>
|
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<form id="export-subtree-form">
|
|
||||||
<div class="modal-body">
|
|
||||||
<div>Export note "<span class="note-title"></span>" and its subtree in the following format:</div>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="radio" name="export-format" id="export-format-tar" value="native-tar" checked>
|
|
||||||
<label class="form-check-label" for="export-format-tar">Native TAR - this is Trilium's native format which preserves all notes' data & metadata.</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="radio" name="export-format" id="export-format-opml" value="opml">
|
|
||||||
<label class="form-check-label" for="export-format-opml">
|
|
||||||
OPML - standard outliner interchange format for text only. Formatting, images, files are not included.
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<div class="form-check disabled">
|
|
||||||
<input class="form-check-input" type="radio" name="export-format" id="export-format-markdown"
|
|
||||||
value="markdown-tar">
|
|
||||||
<label class="form-check-label" for="export-format-markdown">
|
|
||||||
Markdown - TAR archive of Markdown formatted notes
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-primary btn-sm">Export</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -157,9 +157,9 @@
|
|||||||
<div class="dropdown-menu dropdown-menu-right">
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
<a class="dropdown-item" id="show-note-revisions-button" data-bind="css: { disabled: type() == 'file' || type() == 'image' }">Revisions</a>
|
<a class="dropdown-item" id="show-note-revisions-button" data-bind="css: { disabled: type() == 'file' || type() == 'image' }">Revisions</a>
|
||||||
<a class="dropdown-item show-attributes-button"><kbd>Alt+A</kbd> Attributes</a>
|
<a class="dropdown-item show-attributes-button"><kbd>Alt+A</kbd> Attributes</a>
|
||||||
<a class="dropdown-item" id="show-source-button" data-bind="css: { disabled: type() != 'text' }">HTML source</a>
|
<a class="dropdown-item" id="show-source-button" data-bind="css: { disabled: type() != 'text' && type() != 'code' && type() != 'relation-map' && type() != 'search' }">Note source</a>
|
||||||
<a class="dropdown-item" id="upload-file-button">Upload file</a>
|
<a class="dropdown-item" id="upload-file-button">Upload file</a>
|
||||||
<a class="dropdown-item" id="export-note-to-markdown-button" data-bind="css: { disabled: type() != 'text' && type() != 'code' }">Export as markdown</a>
|
<a class="dropdown-item" id="export-note-button" data-bind="css: { disabled: type() != 'text' }">Export note</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -173,7 +173,7 @@
|
|||||||
<% include dialogs/attributes.ejs %>
|
<% include dialogs/attributes.ejs %>
|
||||||
<% include dialogs/branch_prefix.ejs %>
|
<% include dialogs/branch_prefix.ejs %>
|
||||||
<% include dialogs/event_log.ejs %>
|
<% include dialogs/event_log.ejs %>
|
||||||
<% include dialogs/export_subtree.ejs %>
|
<% include dialogs/export.ejs %>
|
||||||
<% include dialogs/jump_to_note.ejs %>
|
<% include dialogs/jump_to_note.ejs %>
|
||||||
<% include dialogs/markdown_import.ejs %>
|
<% include dialogs/markdown_import.ejs %>
|
||||||
<% include dialogs/note_revisions.ejs %>
|
<% include dialogs/note_revisions.ejs %>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user