mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
separate basic and extended paste modes
- basic mode is the default, and includes only HTML elements that can be added/edited easily with the default editor - extended mode is enabled by holding down shift and includes a bunch of other HTML elements
This commit is contained in:
parent
23e0034278
commit
1d3e5787a2
3 changed files with 43 additions and 20 deletions
|
@ -646,8 +646,13 @@ to a cloze type first, via Edit>Change Note Type."""))
|
|||
def doPaste(self, html, internal):
|
||||
if not internal:
|
||||
html = self._pastePreFilter(html)
|
||||
self.web.eval("pasteHTML(%s, %s);" % (
|
||||
json.dumps(html), json.dumps(internal)))
|
||||
extended = self.mw.app.queryKeyboardModifiers() & Qt.ShiftModifier
|
||||
if extended:
|
||||
extended = "true"
|
||||
else:
|
||||
extended = "false"
|
||||
self.web.eval("pasteHTML(%s, %s, %s);" % (
|
||||
json.dumps(html), json.dumps(internal), extended))
|
||||
|
||||
def doDrop(self, html, internal):
|
||||
self.web.evalWithCallback("makeDropTargetCurrent();",
|
||||
|
|
|
@ -99,6 +99,8 @@ class AnkiWebView(QWebEngineView):
|
|||
QShortcut(key, self,
|
||||
context=Qt.WidgetWithChildrenShortcut,
|
||||
activated=fn)
|
||||
QShortcut(QKeySequence("ctrl+shift+v"), self,
|
||||
context=Qt.WidgetWithChildrenShortcut, activated=self.onPaste)
|
||||
|
||||
self.focusProxy().installEventFilter(self)
|
||||
|
||||
|
|
|
@ -300,18 +300,18 @@ function hideDupes() {
|
|||
$("#dupes").hide();
|
||||
}
|
||||
|
||||
var pasteHTML = function (html, internal) {
|
||||
html = filterHTML(html, internal);
|
||||
var pasteHTML = function (html, internal, allowedTags) {
|
||||
html = filterHTML(html, internal, allowedTags);
|
||||
setFormat("inserthtml", html);
|
||||
};
|
||||
|
||||
var filterHTML = function (html, internal) {
|
||||
var filterHTML = function (html, internal, extendedMode) {
|
||||
// wrap it in <top> as we aren't allowed to change top level elements
|
||||
var top = $.parseHTML("<ankitop>" + html + "</ankitop>")[0];
|
||||
if (internal) {
|
||||
filterInternalNode(top);
|
||||
} else {
|
||||
filterNode(top);
|
||||
filterNode(top, extendedMode);
|
||||
}
|
||||
var outHtml = top.innerHTML;
|
||||
//console.log(`input html: ${html}`);
|
||||
|
@ -319,20 +319,31 @@ var filterHTML = function (html, internal) {
|
|||
return outHtml;
|
||||
};
|
||||
|
||||
var allowedTags = {};
|
||||
var allowedTagsBasic = {};
|
||||
var allowedTagsExtended = {};
|
||||
|
||||
var TAGS_WITHOUT_ATTRS = ["H1", "H2", "H3", "P", "DIV", "BR", "LI", "UL",
|
||||
"OL", "B", "I", "U", "BLOCKQUOTE", "CODE", "EM",
|
||||
"STRONG", "PRE", "SUB", "SUP", "TABLE", "DD", "DT", "DL"];
|
||||
for (var i = 0; i < TAGS_WITHOUT_ATTRS.length; i++) {
|
||||
allowedTags[TAGS_WITHOUT_ATTRS[i]] = {"attrs": []};
|
||||
var TAGS_WITHOUT_ATTRS = ["P", "DIV", "BR",
|
||||
"B", "I", "U", "EM", "STRONG", "SUB", "SUP"];
|
||||
var i;
|
||||
for (i = 0; i < TAGS_WITHOUT_ATTRS.length; i++) {
|
||||
allowedTagsBasic[TAGS_WITHOUT_ATTRS[i]] = {"attrs": []};
|
||||
}
|
||||
|
||||
allowedTags["A"] = {"attrs": ["HREF"]};
|
||||
allowedTags["TR"] = {"attrs": ["ROWSPAN"]};
|
||||
allowedTags["TD"] = {"attrs": ["COLSPAN", "ROWSPAN"]};
|
||||
allowedTags["TH"] = {"attrs": ["COLSPAN", "ROWSPAN"]};
|
||||
allowedTags["IMG"] = {"attrs": ["SRC"]};
|
||||
TAGS_WITHOUT_ATTRS = ["H1", "H2", "H3", "LI", "UL", "BLOCKQUOTE", "CODE",
|
||||
"PRE", "TABLE", "DD", "DT", "DL"];
|
||||
for (i = 0; i < TAGS_WITHOUT_ATTRS.length; i++) {
|
||||
allowedTagsExtended[TAGS_WITHOUT_ATTRS[i]] = {"attrs": []};
|
||||
}
|
||||
|
||||
allowedTagsBasic["IMG"] = {"attrs": ["SRC"]};
|
||||
|
||||
allowedTagsExtended["A"] = {"attrs": ["HREF"]};
|
||||
allowedTagsExtended["TR"] = {"attrs": ["ROWSPAN"]};
|
||||
allowedTagsExtended["TD"] = {"attrs": ["COLSPAN", "ROWSPAN"]};
|
||||
allowedTagsExtended["TH"] = {"attrs": ["COLSPAN", "ROWSPAN"]};
|
||||
|
||||
// add basic tags to extended
|
||||
Object.assign(allowedTagsExtended, allowedTagsBasic);
|
||||
|
||||
// filtering from another field
|
||||
var filterInternalNode = function (node) {
|
||||
|
@ -348,7 +359,7 @@ var filterInternalNode = function (node) {
|
|||
};
|
||||
|
||||
// filtering from external sources
|
||||
var filterNode = function (node) {
|
||||
var filterNode = function (node, extendedMode) {
|
||||
// text node?
|
||||
if (node.nodeType === 3) {
|
||||
return;
|
||||
|
@ -363,14 +374,19 @@ var filterNode = function (node) {
|
|||
nodes.push(node.childNodes[i]);
|
||||
}
|
||||
for (i = 0; i < nodes.length; i++) {
|
||||
filterNode(nodes[i]);
|
||||
filterNode(nodes[i], extendedMode);
|
||||
}
|
||||
|
||||
if (node.tagName === "ANKITOP") {
|
||||
return;
|
||||
}
|
||||
|
||||
var tag = allowedTags[node.tagName];
|
||||
var tag;
|
||||
if (extendedMode) {
|
||||
tag = allowedTagsExtended[node.tagName];
|
||||
} else {
|
||||
tag = allowedTagsBasic[node.tagName];
|
||||
}
|
||||
if (!tag) {
|
||||
if (!node.innerHTML) {
|
||||
node.parentNode.removeChild(node);
|
||||
|
|
Loading…
Reference in a new issue