Last active
September 13, 2019 14:38
-
-
Save ile/8a08c23b5ae0f331dee8ca062fdef40d to your computer and use it in GitHub Desktop.
Quill "soft" linebreaks (<br> inside <p>) ... requires https://github.com/ilkkah/quillty
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Delta from 'quill-delta'; | |
function create(Quill) { | |
const Break = Quill.import('blots/break'); | |
const Embed = Quill.import('blots/embed'); | |
const Parchment = Quill.import('parchment'); | |
const Inline = Quill.import('blots/inline'); | |
const TextBlot = Quill.import('blots/text'); | |
const Block = Quill.import('blots/block'); | |
const LINEBREAK_CHAR = '\u000b' | |
function lineBreakMatcher() { | |
var newDelta = new Delta(); | |
newDelta.insert({'linebreak': ''}); | |
return newDelta; | |
} | |
class SmartBreak extends Parchment.EmbedBlot { | |
static create(value) { | |
let node = super.create(); | |
return node; | |
} | |
length () { | |
return 1; | |
} | |
value () { | |
return LINEBREAK_CHAR | |
} | |
static value(node) { | |
return LINEBREAK_CHAR; | |
} | |
insertInto(parent, ref) { | |
Embed.prototype.insertInto.call(this, parent, ref) | |
} | |
} | |
SmartBreak.blotName = 'linebreak'; | |
SmartBreak.className = 'linebreak'; | |
SmartBreak.tagName = 'BR' | |
Quill.register(SmartBreak, true) | |
var optionsModules = { | |
clipboard: { | |
matchers: [ | |
['BR', lineBreakMatcher] | |
] | |
} | |
} | |
// var quill = new Quill('.editor', options); | |
// var length = quill.getLength() | |
// var text = quill.getText(length - 2, 2) | |
// // Remove extraneous new lines | |
// if (text === '\n\n') { | |
// quill.deleteText(quill.getLength() - 2, 2) | |
// } | |
class MyBlock extends Block { | |
insertAt(index, value, def) { | |
if (def != null) return super.insertAt(index, value, def); | |
if (value.length === 0) return; | |
let lines = value.split('\n'); | |
let text = lines.shift(); | |
let textparts = text.split(LINEBREAK_CHAR); | |
// We'll keep track the position of text parts | |
var pos = index; | |
textparts.forEach((textpart, i) => { | |
if (textpart.length > 0) { | |
if (pos < this.length() - 1 || this.children.tail == null) { | |
super.insertAt(Math.min(pos, this.length() - 1), textpart); | |
} else { | |
this.children.tail.insertAt(this.children.tail.length(), textpart); | |
} | |
this.cache = {}; | |
} | |
pos += textpart.length; | |
// don't insert after the last part ... | |
if (i !== textparts.length - 1) { | |
if (pos < this.length() - 1 || this.children.tail == null) { | |
super.insertAt(Math.min(pos, this.length() - 1), 'linebreak', true); | |
} else { | |
this.children.tail.insertAt(this.children.tail.length(), 'linebreak', true); | |
} | |
pos += 1; | |
} | |
}); | |
let block = this; | |
lines.reduce(function(index, line) { | |
block = block.split(index, true); | |
block.insertAt(0, line); | |
return line.length; | |
}, index + text.length); | |
} | |
// Why position(): | |
// A position() function is normally used for leafs only and in the old implementation a block | |
// couldn't be a leaf, but in this implementation it can be. (At least that's my take on this.) | |
position(index, inclusive) { | |
const path = this.path(index) | |
return [path[0][0].domNode, path[0][1]]; | |
} | |
// Not totally 100 % sure of the correctness of this. | |
path(index) { | |
let paths = [ super.path(index, null, false), super.path(index, null, true) ]; | |
paths.forEach((path) => { | |
path.forEach((value) => { | |
if (value && value[0] instanceof TextBlot) { | |
return value; | |
} | |
}); | |
}); | |
return paths[1]; | |
} | |
} | |
Quill.register('formats/block', MyBlock, true) | |
return optionsModules; | |
} | |
export default create; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment