refactor(templates): major additions and refactoring for the Templates plugin.
Summary:
Adds several new features to the templates plugin, fixes some existing bugs, and
refactors existing code.
New Plugin Features/Fixes:
- Changes the templates editor in preferences to allow variables to be entered with
`{{brackets}}`. Handles many contenteditable complexities to implement.
- Better interaction for renaming and deleting of templates in the editor.
- Changes tabbing behavior when using templates. Tabbing between variables now wraps
around, and typing tab from outside a variable region highlights the closest region.
- Prevents "Enter" key in the composer when inside a variable region, and strips all
formatting/tags from within the region - this prevents major contenteditable issues
that can result in inline CSS in the style of our variable regions, which will not be
removed when sending.
- Shows a warning when choosing a template if it will replace existing text in a draft.
- Prevents invalid characters in template names (due to filenames, esp. on Windows),
and shows an error message. Strips these characters from draft titles when making a
template.
- Fixes a bug where TemplateStore's initialization code was being called multiple times.
New N1 code:
- Several new methods in `DOMUtils` useful for working with contenteditable.
- Implement some missing methods in `Editor`
Refactor:
- Major refactor/rewrite of template composer extension to use new DOMUtils methods
and simplify the logic (while adding new functionality).
Remaining issues:
- `preferences-tempaltes.cjsx` and `template-editor.coffee` should be rewritten in ES6
for consistency
- Need tests for new DOMUtils functions and for new Templates plugin code.
Test Plan: manual, need to update specs
Reviewers: evan, bengotow
Reviewed By: evan, bengotow
Subscribers: juan
Differential Revision: https://phab.nylas.com/D2382
2015-12-30 07:11:04 +08:00
|
|
|
{DOMUtils, ContenteditableExtension} = require 'nylas-exports'
|
|
|
|
|
|
|
|
class TemplateEditor extends ContenteditableExtension
|
|
|
|
|
|
|
|
|
2015-12-31 08:51:23 +08:00
|
|
|
@onContentChanged: ({editor}) ->
|
refactor(templates): major additions and refactoring for the Templates plugin.
Summary:
Adds several new features to the templates plugin, fixes some existing bugs, and
refactors existing code.
New Plugin Features/Fixes:
- Changes the templates editor in preferences to allow variables to be entered with
`{{brackets}}`. Handles many contenteditable complexities to implement.
- Better interaction for renaming and deleting of templates in the editor.
- Changes tabbing behavior when using templates. Tabbing between variables now wraps
around, and typing tab from outside a variable region highlights the closest region.
- Prevents "Enter" key in the composer when inside a variable region, and strips all
formatting/tags from within the region - this prevents major contenteditable issues
that can result in inline CSS in the style of our variable regions, which will not be
removed when sending.
- Shows a warning when choosing a template if it will replace existing text in a draft.
- Prevents invalid characters in template names (due to filenames, esp. on Windows),
and shows an error message. Strips these characters from draft titles when making a
template.
- Fixes a bug where TemplateStore's initialization code was being called multiple times.
New N1 code:
- Several new methods in `DOMUtils` useful for working with contenteditable.
- Implement some missing methods in `Editor`
Refactor:
- Major refactor/rewrite of template composer extension to use new DOMUtils methods
and simplify the logic (while adding new functionality).
Remaining issues:
- `preferences-tempaltes.cjsx` and `template-editor.coffee` should be rewritten in ES6
for consistency
- Need tests for new DOMUtils functions and for new Templates plugin code.
Test Plan: manual, need to update specs
Reviewers: evan, bengotow
Reviewed By: evan, bengotow
Subscribers: juan
Differential Revision: https://phab.nylas.com/D2382
2015-12-30 07:11:04 +08:00
|
|
|
|
|
|
|
# Run through and remove all code nodes that are invalid
|
|
|
|
codeNodes = editor.rootNode.querySelectorAll("code.var.empty")
|
|
|
|
for codeNode in codeNodes
|
|
|
|
# remove any style that was added by contenteditable
|
|
|
|
codeNode.removeAttribute("style")
|
|
|
|
# grab the text content and the indexable text content
|
|
|
|
text = codeNode.textContent
|
|
|
|
indexText = DOMUtils.getIndexedTextContent(codeNode).map( ({text}) -> text ).join("")
|
|
|
|
# unwrap any code nodes that don't start/end with {{}}, and any with line breaks inside
|
|
|
|
if not text.startsWith("{{") or not text.endsWith("}}") or indexText.indexOf("\n")>-1
|
|
|
|
editor.whilePreservingSelection ->
|
|
|
|
DOMUtils.unwrapNode(codeNode)
|
|
|
|
|
2016-01-13 04:44:22 +08:00
|
|
|
# Attempt to sanitize extra nodes that may have been created by contenteditable on certain text editing
|
|
|
|
# operations (insertion/deletion of line breaks, etc.). These are generally <span>, but can also be
|
|
|
|
# <font>, <b>, and possibly others. The extra nodes often grab CSS styles from neighboring elements
|
|
|
|
# as inline style, including the yellow text from <code> nodes that we insert. This is contenteditable
|
|
|
|
# trying to be "smart" and preserve styles, which is very undesirable for the <code> node styles. The
|
|
|
|
# below code is a hack to prevent yellow text from appearing.
|
|
|
|
for node in editor.rootNode.querySelectorAll("*")
|
|
|
|
if not node.className and node.style.color == "#c79b11"
|
2015-12-31 10:13:48 +08:00
|
|
|
editor.whilePreservingSelection ->
|
2016-01-13 04:44:22 +08:00
|
|
|
DOMUtils.unwrapNode(node)
|
|
|
|
|
|
|
|
for node in editor.rootNode.querySelectorAll("font")
|
|
|
|
if node.color == "#c79b11"
|
|
|
|
editor.whilePreservingSelection ->
|
|
|
|
DOMUtils.unwrapNode(node)
|
refactor(templates): major additions and refactoring for the Templates plugin.
Summary:
Adds several new features to the templates plugin, fixes some existing bugs, and
refactors existing code.
New Plugin Features/Fixes:
- Changes the templates editor in preferences to allow variables to be entered with
`{{brackets}}`. Handles many contenteditable complexities to implement.
- Better interaction for renaming and deleting of templates in the editor.
- Changes tabbing behavior when using templates. Tabbing between variables now wraps
around, and typing tab from outside a variable region highlights the closest region.
- Prevents "Enter" key in the composer when inside a variable region, and strips all
formatting/tags from within the region - this prevents major contenteditable issues
that can result in inline CSS in the style of our variable regions, which will not be
removed when sending.
- Shows a warning when choosing a template if it will replace existing text in a draft.
- Prevents invalid characters in template names (due to filenames, esp. on Windows),
and shows an error message. Strips these characters from draft titles when making a
template.
- Fixes a bug where TemplateStore's initialization code was being called multiple times.
New N1 code:
- Several new methods in `DOMUtils` useful for working with contenteditable.
- Implement some missing methods in `Editor`
Refactor:
- Major refactor/rewrite of template composer extension to use new DOMUtils methods
and simplify the logic (while adding new functionality).
Remaining issues:
- `preferences-tempaltes.cjsx` and `template-editor.coffee` should be rewritten in ES6
for consistency
- Need tests for new DOMUtils functions and for new Templates plugin code.
Test Plan: manual, need to update specs
Reviewers: evan, bengotow
Reviewed By: evan, bengotow
Subscribers: juan
Differential Revision: https://phab.nylas.com/D2382
2015-12-30 07:11:04 +08:00
|
|
|
|
|
|
|
# Find all {{}} and wrap them in code nodes if they aren't already
|
|
|
|
# Regex finds any {{ <contents> }} that doesn't contain {, }, or \n
|
|
|
|
# https://regex101.com/r/jF2oF4/1
|
|
|
|
ranges = editor.regExpSelectorAll(/\{\{[^\n{}]*?\}\}/g)
|
|
|
|
for range in ranges
|
|
|
|
if not DOMUtils.isWrapped(range, "CODE")
|
|
|
|
# Preserve the selection based on text index within the range matched by the regex
|
|
|
|
selIndex = editor.getSelectionTextIndex(range)
|
|
|
|
codeNode = DOMUtils.wrap(range,"CODE")
|
|
|
|
codeNode.className = "var empty"
|
|
|
|
codeNode.textContent = codeNode.textContent # Sets node contents to just its textContent, strips HTML
|
|
|
|
if selIndex?
|
|
|
|
editor.restoreSelectionByTextIndex(codeNode, selIndex.startIndex, selIndex.endIndex)
|
|
|
|
|
|
|
|
|
|
|
|
module.exports = TemplateEditor
|