GithubHelp home page GithubHelp logo

guardian / scribe Goto Github PK

View Code? Open in Web Editor NEW
3.5K 159.0 245.0 5.5 MB

DEPRECATED: A rich text editor framework for the web platform

Home Page: http://guardian.github.io/scribe/

License: Apache License 2.0

JavaScript 98.48% HTML 0.31% Shell 1.20%

scribe's Introduction

THIS PROJECT IS DEPRECATED - You can find more information about this in our blog post, Leaving Scribe. In summary:

  • We have no plans to add features to Scribe but may make critical updates throughout the period that we continue to use instances of Scribe internally
  • We recommend forking the project in order to do any feature work as we will not be moving the Scribe repository out of the Guardian organisation
  • In time we hope to be able to open source the new text editor we are working on

Scribe

A rich text editor framework for the web platform, with patches for browser inconsistencies and sensible defaults.

Status

Build Status Join the chat at https://gitter.im/guardian/scribe

Description

For an introduction, you may want to read the blog post Inside the Guardian’s CMS: meet Scribe, an extensible rich text editor.

Please note: There is a lot of missing documentation for Scribe and many of its plugins. We plan to improve this, however in the meantime we encourage you to look at the code. Scribe is very small in comparison to other libraries of its kind.

You can join us on IRC at [#scribejs] on freenode, or via the Google Group.

See an example.

Scribe only actively supports a sub-set of browsers.

Core

At the core of Scribe we have:

Patches

Scribe patches many browser inconsistencies in the native command API.

Installation

bower install scribe

Alternatively, you can access the distribution files through GitHub releases.

Usage Example

Scribe is an AMD module:

require(['scribe', 'scribe-plugin-blockquote-command', 'scribe-plugin-toolbar'],
  function (Scribe, scribePluginBlockquoteCommand, scribePluginToolbar) {
  var scribeElement = document.querySelector('.scribe');
  // Create an instance of Scribe
  var scribe = new Scribe(scribeElement);

  // Use some plugins
  scribe.use(scribePluginBlockquoteCommand());
  var toolbarElement = document.querySelector('.toolbar');
  scribe.use(scribePluginToolbar(toolbarElement));
});

You can see a live example here, or view the code here.

Also be sure to check the examples directory for an AMD syntax example as well as a CommonJS (browserify) example.

Options

allowBlockElements
Enable/disable block element mode (enabled by default)
undo: { enabled: false }
Enable/disable Scribe's custom undo manager
defaultCommandPatches
Defines which command patches should be loaded by default
defaultPlugins
Defines which of Scribe's built-in plugins should be active
defaultFormatters
Defines which of Scribe's default formatters should be active

For detailed documentation see the wiki page on options.

Architecture

A plugin is simply a function that receives Scribe as an argument:

function myPlugin(scribe) {}

A consumer can then use your plugin with Scribe.use:

scribe.use(myPlugin);

Plugins may package whatever functionality you desire, and you are free to use native APIs to do so. However, you are required to wrap any DOM manipulation in a transaction, so that we can capture state changes for the history. For example:

function myPlugin(scribe) {
  scribe.transactionManager.run(function () {
    // Do some fancy DOM manipulation
  });
}

Browser Support

Moved to the Github Wiki

Plugins

Scribe has a rich plugin ecosystem that expands and customises what it can do.

See the wiki for a list of plugins and how to create new ones

FAQ

See the wiki's FAQ

scribe's People

Contributors

aaalsaleh avatar aleludovici avatar alexeygolev avatar bahlo avatar bryant1410 avatar christopherliu avatar code-smith avatar cutandpastey avatar danburzo avatar davidtobin avatar edeustace avatar es avatar gitter-badger avatar hmgibson23 avatar jamespamplin avatar katebee avatar kekeblom avatar mattandrews avatar regiskuckaertz avatar rf- avatar richieahb avatar robinedman avatar rrees avatar samvasko avatar shaundillon avatar shaunnetherby avatar sihil avatar tbonnin avatar theefer avatar tootallnate avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scribe's Issues

Create phases for formatters

There are currently ordering issues with formatters.

Enclosed is a list of desired formatters. Please comment if you have any others. From here I can figure out how to group them into phases.

Plain Text

  • Convert text separated by two new line characters into two HTML P elements
  • Convert text separated by one new line character into text separated by a HTML BR element
  • Escape HTML characters

HTML

  • Implicit validation
  • - p>h1 => p+h1
  • - =>
  • Replace non-breaking space HTML entities with normal space (when appropriate?)
  • Translating node names e.g. b => strong
  • Remove HTML comments
  • Remove inner text of SCRIPT and STYLE elements (configurable?)
<p>1</p>
<p>2</p>
=>
<p>1</p><p>2</p>
  • Sanitise elements according to whitelist (when removing block elements, replace with configurable block element)
  • - Removing non-whitelisted elements by node name
  • - Removing non-whitelisted attributes
  • - Removing non-whitelisted attribute values (lists, strings, regular expressions)
  • Reposition invalid nested block elements (configurable block elements)
  • Condense whitespace around block elements to avoid erroneous text nodes (configurable block elements)
  • Consolidate consecutive text nodes
  • Wrap isolated text in P elements (if in block mode)
  • Insert BRs into elements to ensure they are selectable

Exporters

  • Remove trailing BRs

allow for different block elements

right now the library assumes that <p> is the desired block element, it'd be great to support other elements along with nested block structures.

After making a selection and bolding, selection disappears

After making a selection of a portion of a text and bolding (by for example pressing command-b), text gets bolded but selection disappears. This is a bit counter intuitive in comparison with other WYSIWYG editors (like Word) where you can keep pressing a button and it is toggling bold on and off.

Bold is just an example. :-)

This happens at least in Chrome.

When enabling bold without a selection it cannot be disabled

If I have a caret position inside a normal text and I click on "bold" button and start typing new text is bold. This is good. But if I click on "bold" button and then change my mind, I cannot click again to disable/disengage. I have to move caret somewhere else for this to happen. Or type something and delete.

Tested in Chrome 34.

Clean up bogus `BR` elements

Browsers need to insert something inside of an empty element in order for the caret to be positioned there (AFAIK). You wouldn’t be able to place your caret inside of <p></p> because there’s no text node/element.

This hasn’t been fixed because there were bigger fish to try, but could easily be done as a “formatter” (perhaps).

Curly quotes wrong after punctuation

Using the curly quote plugin, typing something ("words") results in something (”words”) (i.e. the first curly quotes is a closing one, where it should be an opening one).

The logic needs to be adapted to avoid considering punctuation (typically parentheses, maybe other things) as a character that may be ending a word.

Clarify installation instruction

Installation instruction are not clear or covering everything needed to get Scribe running. I have two main issues with your current "instructions":

  1. Running bower install scribe is not enough to get it working.
  2. No clear list of dependencies/requirements anywhere

You should keep in mind that not everyone is a JS guru used to all the tooling mentioned in the README. Scribe seems really nice, but given how hard it is to even get running and there is no help available, having proper instructions should be a priority rather than adding features.

I would write it up myself, but given that after 2h I still failed to get Scribe to work at all, I'll leave it to the contributors to write clear instructions.

Usage with browserify

Forgive me if there's an obvious answer to this question. I spent some time yesterday trying to use this in a project, and got stuck because of the AMD format. Is there a simple way to use this with browserify?

Improve undo history items

It would be nice if we could set the debounce on inputs so undo/redo don't trigger for every key.

Could be an option:

Scribe(el, { debounce: 50 });

Or the ability to monkeypatch the input event would be great too.

Adding an image

Plugin to add an image by a URL. Also should be able to set width and height attributes.

`insertPlainText` after initialization throws exception

Steps to reproduce:

  • Clone scribe
  • Checkout gh-pages
  • Edit example.js, line 103, from scribe.setContent('<p>Hello, World!</p>'); to scribe.insertPlainText('Hello, World!');
  • Open the example through a webserver.
  • See Uncaught TypeError: Cannot call method 'cloneRange' of undefined in selection.js, line 28.

OS: Mac OS X Maverick
Chrome: 33.0.1750.152

Can you use Scribe with a simple <script> tag

I want to include scribe like i do jquery into my project (I do not want to use require.js) - is this currently possible ? (and sorry if this is a dumb question, I looked through the issues and couldnt figure it out - and two weeks ago I could not do this)

Unbind/destroy

When destroying a Scribe instance, it should clean-up all references and DOM event bindings, including in any plugins being used.

HTML pastes as plaintext in Firefox on Windows

There is a bug in Firefox on Windows (I believe this one) that causes pasted HTML to be identified as text/plain rather than text/html. That causes this check to fail and the content to be inserted as plaintext.

This appears to be an issue only with this particular combination of browser and OS. Firefox 28 on OS X 10.9.2 correctly identifies pasted HTML as text/html, while Firefox 28 on Windows 7 x86 does not. I don't have any other versions of Windows available to test on.

As a workaround, I added a useragent check to force Scribe to use the non-Clipboard API method of pasting when in Firefox on Windows. I'm sure there's a better way to do it :P

Sanitizing with replacement

Currently sanitizing input just removes elements and attributes. I am thinking that sometimes it would be better to replace them with some other element. For example, big headings could be replaced with the one heading used in your content. Current code does not allow this, but I could implement it. I am just not sure about API. Maybe something like:

h1: {
  _replace: 'h2'
}

So field names starting with _ would be special and not attributes.

Add UMD

This module should work in CommonJS, AMD, and browser globals. Currently it only works for AMD.

Ideally this wrapping would be done as part of the build process.

Re. #77

Speed up the CI

CI is currently very slow. It takes 10-14 minutes to run each job in the Travis matrix, for example: https://travis-ci.org/guardian/scribe/builds/20491312. We should really see if we can speed this up.

One idea: we currently tear down and reload the view before each test. This is a bottleneck because of the tunnelled HTTP requests. Could we just re-use the page session?

Output textarea

If you write something in the ouput textarea, even if it's html or plain text, any commands done in the input textarea will not work, neither will be entering of more text in that textarea. I have tested this on Firefox 28 and Chrome 34 on Windows XP. I recomand changing the textarea to disabled and the background color to white and color of the text to black.
screenshot 2014-04-11 14 25 35
screenshot 2014-04-11 14 23 07

Link and unlink actions could be combined

I think that current intelligent unlink action could be combined with link. If you are inside a link and you invoke link, you should simply get an option to edit the link with a button to unlink everything. A separate action to unlink is probably unnecessary and strange for users.

Duplicated code when using Scribe and plugins: How to manage packages?

If two plugins require the same modules, the consumer will have duplicated code (duplicated AMD modules).

Example

Here is an example of what RequireJS creates when walking the dependency graph of the scribe-plugin-sanitizer library.

Source code (master branch): https://github.com/guardian/scribe-plugin-sanitizer/blob/master/src/scribe-plugin-sanitizer.js
Compiled distribution code (dist branch): https://github.com/guardian/scribe-plugin-sanitizer/blob/dist/scribe-plugin-sanitizer.js

If another plugin had the same dependencies, and I as a consumer was using both of those plugins, I would have quite a lot of duplicated code in my environment. Furthermore, my AMD loader might complain about duplicate module IDs.

Ideas

This is an artefact of using the distributed versions instead of building from source on the consumer’s end. Traditionally, libraries in the front-end ecosystem solve this problem by requiring consumers to load the library themselves and make it available on the window object, for use by the library. This is not something we want to do because it sucks to have globals and throws all the ideas of dependency management, dependency versioning, and encapsulation, out of the window.

For the time being, the consumer can work around this by compiling from source themselves.

Ideally, plugins would define their dependencies with versions, and then the consumer would create an optimised bundle themselves. So:

  • If plugin a and b use the find module from [email protected], the resulting bundle would only contain one find module
  • If plugin a used the find module from [email protected] and plugin b used the find module from [email protected], the resulting bundle would contain two find modules. The bundled plugins would know which respective find module to use.

N.B: I am only using lodash-amd as an example of a dependency.

Herein we should discuss the requirements of the package manager, module format (we would like to move to using ES6 modules), and module loader. I think we need consumers to create their own bundles instead of using compiled distribution code, however:

  • with RequireJS this would require the consumer to define the paths to the dependencies of the plugins, e.g. the path to lodash-amd in Bower;
  • as far as I know Bower will not allow you to install two versions of the same library. Furthermore, how would the module optimiser create two unique find modules? RequireJS does not support this, as far as I can tell.

/cc @guybedford

Removing scribe instance.

What would be the best way to remove scribe instance?

Scenario in my project:

  1. Multiple editable divs on a page.
  2. Attaching scribe to specific div on focus event.
  3. Removing scribe instance on blur event (after finishing editing text)

Basically I don't want to have separate scribe instance per every div, since this might be high memory consuming.

Sanitize by allowing just a set of CSS classes on a element

It seems to me that currently there is no way to allow a set of CSS classes to be applied to an element, but not any other or any other attribute. You can just enable/disable attribute as a whole? Here I see that you can specify an exact value for the attribute, but not really a list of values for CSS classes?

Clicking h2-button creates multiple h2

In the editor: Mark any word in the texteditor (not the output) and click h2 multiple times.

Instead of expected: <h2>Hello, World!</h2> I get: <h2>Hello, World!</h2><h2></h2><p></p><h2></h2><p></p>

Simpler formatter API to transform DOM trees

A simpler formatter API would allow reusing a parsed working DOM tree and use immutable mapping to compose small transformations (e.g. unwrap SPAN, map inline style to element, replace element X by Y, filter classes, etc).

This is a WIP spike, use this issue for tracking.

Editing just created link does not work in Firefox

If I select word "World" in demo in Firefox 28 and I click on link button, and create a link, link is created and selection seemingly keeps link selected. But when I click on the link button again, to edit the link, I get initial empty dialog box.

In Chrome the same series of steps works.

Fix Travis builds for pull requests with foreign origins

Sadly the integration tests won’t run for pull requests when the source repository !== the target repository. See these Travis docs for details why – we’re using encrypted environment variables to store our access key for Sauce Labs.

It looks like AngularJS, who share a similar setup, have decided not to bother encrypting their access key for Sauce Labs.

Solutions on the Travis end of things are being discussed at travis-ci/travis-ci#1946.

For now we should skip the tests if one of the expected encrypted environment variables is not found.

/cc @saucelabs

A way to use editor in inline-only mode

A way to use editor in inline-only mode. So without any block elements, but even without line breaks. Just a long rich-text line of text. It seems that even with allowBlockElements set to false and using sanitizer plugin to remove all except basic inline elements this is not possible.

Thoughts on using Rangy

Rangy is a cross-browser JavaScript range and selection library. I think that using it could help make Scribe cross-browser. Selection API is one of parts which is not really cross-browser but it is heavily used in Scribe.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.