Skip to content

Instantly share code, notes, and snippets.

@ile
Last active September 13, 2019 14:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ile/8a08c23b5ae0f331dee8ca062fdef40d to your computer and use it in GitHub Desktop.
Save ile/8a08c23b5ae0f331dee8ca062fdef40d to your computer and use it in GitHub Desktop.
Quill "soft" linebreaks (<br> inside <p>) ... requires https://github.com/ilkkah/quillty
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;
@ile
Copy link
Author

ile commented Feb 2, 2019

this.quill.keyboard.addBinding({
  key: 'Enter',
  shiftKey: true,
  ctrlKey: true
}, function(range, context) {
  var currentLeaf, lineFormats, nextLeaf;
  if (range.length > 0) {
    this.quill.scroll.deleteAt(range.index, range.length);
  }
  lineFormats = Object.keys(context.format).reduce(function(formats, format) {
    if (this.quill.scroll.query(format, Scope.BLOCK) && !Array.isArray(context.format[format])) {
      formats[format] = context.format[format];
    }
    return formats;
  }, {});
  currentLeaf = this.quill.getLeaf(range.index)[0];
  nextLeaf = this.quill.getLeaf(range.index + 1)[0];
  this.quill.insertText(range.index, '\u000b', lineFormats, Quill.sources.USER);
  if (nextLeaf === null || (currentLeaf.parent !== nextLeaf.parent)) {
    this.quill.insertText(range.index, '\u000b', Quill.sources.USER);
  }
  this.quill.setSelection(range.index + 1, Quill.sources.SILENT);
  this.quill.focus();
  Object.keys(context.format).forEach(function(name) {
    if (lineFormats[name] !== null) {
      return;
    }
    if (Array.isArray(context.format[name])) {
      return;
    }
    if (name === 'link') {
      return;
    }
    return this.quill.format(name, context.format[name], Quill.sources.USER);
  });
  return true;
});

@JustinElst
Copy link

Why is https://github.com/ilkkah/quillty required for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment