sielay
January 27, 2016, 1:48pm
1
TL;DR - way to get content from selection is?
I tried few examples you posted around, but I can’t workout how to make command that would wrap selected text by my node/widget.
I create something like twitterable quote. I wrap selected content with
<a href="..."><blockquote><p>(content)</p></blockqoute></a>
It works nicely when I render it from data
Twitterable.prototype.serializeDOM = (node, serializer, c, d, e, f, g) => {
let innerContent = '',
innerContentClear = '',
attributes = {
class: 'twitterable'
};
if (node.rendered) {
node.rendered = node.rendered.cloneNode(true)
} else {
try {
if (node && node.content && node.content[0] && node.content[0].type) {
innerContent = serializer.renderNode(node.content.content[0]);
innerContentClear = toText(node.content.content[0]);
}
} catch (e) {
console.error(e);
}
if (serializer.options.serverSide === true) {
attributes.href = 'https://twitter.com/intent/tweet?text=' + encodeURIComponent(innerContentClear + ' ' + serializer.options.uri);
}
node.rendered = elt('a', attributes, [
elt('blockquote', {}, [
elt('p', {},
innerContent)
])]);
}
return node.rendered;
};
But I can’t work out how to enable selecting fragment and wrapping it. I found that it may be good to use code like here:
Twitterable.register('command', 'insert', {
run(pm) {
return pm.tr.replaceSelection(this.create({}));
},
})
Anyhow basing on doc and examples I can’t workout how to:
get reference to selected fragment
what is correct way of passing it to new node (in worst scenario I could do node.content.content.push(selectedNode)
Any ideas or reference?
marijn
January 27, 2016, 2:11pm
2
(As an aside, don’t render the inner content with renderNode
. Use renderAs
instead.)
Is this a block node type? Are you trying to wrap the whole textblock, or only the actually selected text? You can get the content of a selection by calling slice
on the document and passing in the from
and to
from the selection. Is that what you were looking for?
1 Like
sielay
January 27, 2016, 2:34pm
3
In ideal case that would be block. As it create a > blockquote > p
sielay
January 27, 2016, 2:45pm
4
run(pm) {
let content = pm.doc.slice(pm.selection.from, pm.selection.to);
console.log(content);
return pm.tr.replaceSelection(this.create({}));
},
content
is Node of type doc
and nothing in content, even, if I select text.
Sorry, it’s not obvious (what doesn’t mean it’s wrong).
marijn
January 27, 2016, 2:50pm
5
Sorry, my bad, I meant sliceBetween
. But that’ll still yet you a Doc
node, since selections may have an arbitrary shape and can not necessarily be represented as a single node or flat list of nodes.
If you only want to deal with selection within a single textblock, you can do something like
let parent = pm.doc.path(from.path)
if (Pos.samePath(from.path, to.path) && parent.isTextblock) {
// Fragment object containing slice of inline nodes
let content = parent.slice(from.offset, to.offset)
pm.tr.replaceSelection(MY_NODE_TYPE.create(null, content)).apply()
}
1 Like
sielay
January 27, 2016, 3:11pm
6
Thanks, following code works perfectly
Twitterable.prototype.serializeDOM = (node, serializer) => {
let innerContent = '',
innerContentClear = '',
attributes = {
class: 'twitterable'
};
if (node.rendered) {
node.rendered = node.rendered.cloneNode(true)
} else {
try {
if (node && node.content && node.content.content && node.content.content[0].type) {
innerContent = serializer.renderAs(node.content.content[0], 'p');
innerContentClear = toText(node.content.content[0]);
}
} catch (e) {
console.error(e);
}
if (serializer.options.serverSide === true) {
attributes.href = 'https://twitter.com/intent/tweet?text=' + encodeURIComponent(innerContentClear + ' ' + serializer.options.uri);
}
node.rendered = elt('a', attributes, [elt('blockquote', {}, innerContent)]);
}
return node.rendered;
};
Twitterable.register('command', 'insert', {
label: 'Wrap the selection in a block quote',
run(pm) {
let content = pm.doc.sliceBetween(pm.selection.from, pm.selection.to),
node = this.create(null, content.content);
return pm.tr.replaceSelection(node).apply();
},
menuGroup: 'block(46)',
})