Skip to content

Instantly share code, notes, and snippets.

@hongymagic
Last active December 16, 2015 02:29
Show Gist options
  • Save hongymagic/5363135 to your computer and use it in GitHub Desktop.
Save hongymagic/5363135 to your computer and use it in GitHub Desktop.
Discussion on EpicEditor.getSelection API

What are the goals for EpicEditor#getSelection API?

  1. Support insertion, modification and deletion of markdown document
  2. Support entire markdown syntax, possibly more (i.e., github style)
  3. Easy and intuitive, duh
  4. Ability to extend, shrink selection range. I.e., manipulate selection programmatically (not included in this document yet)

Implementation

In my view, there are two ways to go about this problem. The first, is to provide a low-level text editing platform which users can use to implement their own functions to perform three operations outlined above. Second, is to provide a markdown specific API.

It is possible to have both implementations, it just means that the second implementation will use the low-level text editing API itself.

Note

API/function names are not important at this stage, should focus on an approach, then we can come up with the names quite easily as most of the names should be intuitive.

Blockers?

Cross node editing is going to be epic hard.

Idea 1: Low-level text editing

Here we have a custom selection object:

var selection = editor.getSelection();

Text

var text = selection.getText(); 
// => Hello   (string)

Headings

selection.prepend('# ');
// => # Hello

selection.surroundWith('#');
// => # Hello #

Bold, italic, inline code

selection.surroundWith('**'); 
// => **Hello** (edits document)

Links

selection.replaceWith('[' + text + '](' + link ')');
// => [Hello](https://github.com)

selection.replaceWith('[text][github]');
editor.append('[github]: https://github.com');
// => [Hello][github]
// => [github]: https://github.com

Blockquote

selection.prependLines('> ');
=> > Hello

Code blocks

selection.prependLines('\t');
selection.prependLines('    ');
selection.indent();
=>     Hello

Insertion

selection.prepend('Oh! ');
// => Oh!  Hello

selection.append(' World!');
// => Hello World!

selection.insertAt(2, 'eee');
// => Heeeello

Q: How to handle new lines?

Deletion

selection.delete();
// =>

Idea 2: Higher-level API

The idea here is to expose specific functions to the client such that a single operation is carried out on selection to mutate the current state (of the selection).

Here we have a selection API:

var selection = editor.getSelection();

Text

var text = selection.getText(); 
// => Hello   (string)

Bold

selection.bold();
// => **Hello**

Italic, inline-code

// Excuse the ES6 style :P
['italic', 'code'].forEach((style) => selection[style]());
// => *Hello*
// => `Hello`

Links

var url = 'https://github.com';
selection.link(url);
// => [Hello](https://github.com)

Code blocks, blockquotes

This API will indent each line in the selection.

selection.blockquote();
// => > Hello

selection.codeblock();
// =>     Hello
@OscarGodson
Copy link

Some notes:

  1. Some of the things like bold, italic, blockquote, etc are really nice to have, but EpicEditor supports replacing your editor with any parser. If you did this you'd have to provide an API for setting what a blockquote means in, lets say, wiki.
  2. Should we provide a way to extend these? Something like:
EpicEditor.getSelection.extend('laugh', function (text) {
  return text + 'hahahaha';
});

selection.laugh('That\'s funny'); // => That's funny hahahaha

#2 is less important, but would be really cool. Because we could implement #1 as a selection extension for Markdown.

  1. These should be chainable:
selection.prepend('# ').append(' #'); => '# Hello #'

@hongymagic
Copy link
Author

From other post:

@hongymagic Wow! That's rad. How much code do you think this will take?

I think initial implementation would only take a few hours of testing (on main browsers). Main fear is implementing work arounds.

Do you think, if you're going to do this, we should have editor.js and then like selection.js just so that one file doesn't become too big?

Yeah this is totally the way to go. I think I can base this off some of the code I wrote earlier.

Really, that'd probably be like a dream API. Also, if you moved it outside of editor.js you could make it modular and release it as your own project too. I'm sure this would be incredibly useful to others.

Yeah this sounds explorable.

From this post:

  1. Some of the things like bold, italic, blockquote, etc are really nice to have, but EpicEditor supports replacing your editor with any parser. If you did this you'd have to provide an API for setting what a blockquote means in, lets say, wiki.
  2. Should we provide a way to extend these?

How about leave those out for now. We can easily implement them later based off append, prepend. Could even come as a module as you mentioned earlier.

  1. These should be chainable

Yeah this shouldn't be too more more effort.


I'll start a separate project as a proof of concept, then we can incorporate into the main code base once almost everyone is happy with how the API works. Hard to please everyone nowadays.

@OscarGodson
Copy link

@hongymagic while doing this keep in mind this: OscarGodson/EpicEditor#113

Since this stuff will be the majority of work, maybe throw in some events too if you can like selectionstart selectionend or whatever so I could implement this :) Can't wait to se what you come up with. This would be the majority of the work for the 2nd big feature.

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