@progress/kendo-angular-editor
Advanced tools
Comparing version 0.3.0-dev.201902061710 to 0.3.0-dev.201902121457
@@ -15,6 +15,12 @@ /** | ||
outdent: 'indent-decrease', | ||
alignLeft: 'align-left', | ||
alignCenter: 'align-center', | ||
alignRight: 'align-right', | ||
alignJustify: 'align-justify', | ||
viewSource: 'html', | ||
undo: 'undo', | ||
redo: 'redo', | ||
insertImage: 'image' | ||
insertImage: 'image', | ||
subscript: 'sub-script', | ||
superscript: 'sup-script' | ||
}; |
import { undo, redo } from 'prosemirror-history'; | ||
import { schema } from './schema'; | ||
import { removeMark, toggleBold, toggleItalic, toggleUnderline, toggleStrikethrough, createLink, format, indent, outdent, getHTML, setHTML, insertImage } from '../prosemirror-utils'; | ||
import { alignLeftRules, alignCenterRules, alignRightRules, alignRemoveRules } from './align-rules'; | ||
import { removeMark, toggleBold, toggleItalic, toggleUnderline, toggleStrikethrough, alignBlocks, createLink, format, indent, outdent, getHTML, setHTML, insertImage, toggleSubscript, toggleSuperscript } from '../prosemirror-utils'; | ||
import { toggleOrderedList, toggleUnorderedList } from '../prosemirror-list-utils'; | ||
@@ -11,6 +12,12 @@ var inlineCommand = { | ||
underline: function () { return toggleUnderline; }, | ||
strikethrough: function () { return toggleStrikethrough; } | ||
strikethrough: function () { return toggleStrikethrough; }, | ||
subscript: function () { return toggleSubscript; }, | ||
superscript: function () { return toggleSuperscript; } | ||
}; | ||
var blockCommand = { | ||
format: function (formatAttr) { return format(formatAttr); }, | ||
alignLeft: function () { return alignBlocks(alignLeftRules); }, | ||
alignCenter: function () { return alignBlocks(alignCenterRules); }, | ||
alignRight: function () { return alignBlocks(alignRightRules); }, | ||
alignJustify: function () { return alignBlocks(alignRemoveRules); }, | ||
indent: function () { return indent; }, | ||
@@ -17,0 +24,0 @@ outdent: function () { return outdent; }, |
@@ -0,4 +1,12 @@ | ||
import * as tslib_1 from "tslib"; | ||
import { Schema } from 'prosemirror-model'; | ||
import { serializeDOMAttrs, isEmpty, removeEmptyEntries } from '../util'; | ||
import { isEmpty, serializeDOMAttrs, removeEmptyEntries, removeEntries } from '../util'; | ||
var SLOT = 0; //https://prosemirror.net/docs/guide/#schema.serialization_and_parsing | ||
var commonAttributes = function () { | ||
return { | ||
style: { default: null }, | ||
class: { default: null }, | ||
id: { default: null } | ||
}; | ||
}; | ||
/** | ||
@@ -82,2 +90,20 @@ * @hidden | ||
toDOM: function () { return ['del', SLOT]; } | ||
}, | ||
// :: MarkSpec A subscript mark. Rendered as a `<sub>` element. | ||
// Parse rules also match `vertical-align: sub`. | ||
subscript: { | ||
parseDOM: [ | ||
{ tag: 'sub' }, | ||
{ style: 'vertical-align=sub' } | ||
], | ||
toDOM: function () { return ['sub', SLOT]; } | ||
}, | ||
// :: MarkSpec A superscript mark. Rendered as a `<sup>` element. | ||
// Parse rules also match `vertical-align: super`. | ||
superscript: { | ||
parseDOM: [ | ||
{ tag: 'sup' }, | ||
{ style: 'vertical-align=super' } | ||
], | ||
toDOM: function () { return ['sup', SLOT]; } | ||
} | ||
@@ -98,2 +124,3 @@ }; | ||
group: 'block', | ||
attrs: tslib_1.__assign({}, commonAttributes()), | ||
parseDOM: [{ | ||
@@ -109,5 +136,6 @@ tag: 'p', | ||
group: 'block', | ||
attrs: tslib_1.__assign({}, commonAttributes()), | ||
defining: true, | ||
parseDOM: [{ tag: 'blockquote' }], | ||
toDOM: function () { return ['blockquote', SLOT]; } | ||
toDOM: function (node) { return ['blockquote', removeEmptyEntries(node.attrs), SLOT]; } | ||
}, | ||
@@ -124,3 +152,3 @@ // :: NodeSpec A horizontal (`<hr>`) rule. | ||
heading: { | ||
attrs: { level: { default: 1 } }, | ||
attrs: tslib_1.__assign({ level: { default: 1 } }, commonAttributes()), | ||
content: 'inline*', | ||
@@ -137,3 +165,6 @@ group: 'block', | ||
], | ||
toDOM: function (node) { return ['h' + node.attrs.level, SLOT]; } | ||
toDOM: function (node) { | ||
var attrs = removeEntries(node.attrs, function (key) { return key !== 'level'; }); | ||
return ['h' + node.attrs.level, removeEmptyEntries(attrs), SLOT]; | ||
} | ||
}, | ||
@@ -164,8 +195,3 @@ // :: NodeSpec A code listing. Prevents marks or non-text inline | ||
inline: true, | ||
attrs: { | ||
src: {}, | ||
alt: { default: null }, | ||
width: { default: null }, | ||
height: { default: null } | ||
}, | ||
attrs: tslib_1.__assign({}, commonAttributes(), { src: {}, alt: { default: null }, width: { default: null }, height: { default: null } }), | ||
group: 'inline', | ||
@@ -194,6 +220,7 @@ draggable: true, | ||
listItem: { | ||
attrs: tslib_1.__assign({}, commonAttributes()), | ||
content: 'paragraph block*', | ||
marks: '_', | ||
parseDOM: [{ tag: 'li' }], | ||
toDOM: function () { return ['li', SLOT]; } | ||
toDOM: function (node) { return ['li', removeEmptyEntries(node.attrs), SLOT]; } | ||
}, | ||
@@ -200,0 +227,0 @@ // :: NodeSpec An ordered list. Represented as an `<ol>` element. |
@@ -16,6 +16,7 @@ import { Component, HostBinding, ViewChild, ContentChild, ViewContainerRef, Output, ElementRef, EventEmitter, forwardRef, Input } from '@angular/core'; | ||
import { editorCommands } from './config/commands'; | ||
import { alignRightRules, alignCenterRules, alignRemoveRules, alignLeftRules } from './config/align-rules'; | ||
import { LinkDialogComponent } from './dialogs/link-dialog.component'; | ||
import { SourceDialogComponent } from './dialogs/source-dialog.component'; | ||
import { isMarkActive, activeNodeName, canIndent, canOutdent, getHTML, createContentNode, hasSameMarkup, isInListOfType } from './prosemirror-utils'; | ||
import { ImageDialogComponent } from './dialogs/image-dialog.component'; | ||
import { isMarkActive, activeNodeName, canIndent, canOutdent, getHTML, createContentNode, hasSameMarkup, isInListOfType, isAligned } from './prosemirror-utils'; | ||
function updateToolBar(_a) { | ||
@@ -30,2 +31,4 @@ var state = _a.state; | ||
link: isMarkActive(state, schema.marks.link), | ||
subscript: isMarkActive(state, schema.marks.subscript), | ||
superscript: isMarkActive(state, schema.marks.superscript), | ||
//nodes | ||
@@ -37,2 +40,6 @@ format: activeNodeName(state), | ||
outdent: canOutdent(state, schema.nodes.listItem), | ||
alignLeft: isAligned(state, alignLeftRules), | ||
alignCenter: isAligned(state, alignCenterRules), | ||
alignRight: isAligned(state, alignRightRules), | ||
alignJustify: isAligned(state, alignRemoveRules), | ||
//history | ||
@@ -39,0 +46,0 @@ undo: !undo(state), |
@@ -1,4 +0,5 @@ | ||
import { Node, DOMParser, DOMSerializer, Fragment } from 'prosemirror-model'; | ||
import { TextSelection, AllSelection, NodeSelection } from 'prosemirror-state'; | ||
import { Node, DOMParser, DOMSerializer, Fragment, Slice } from 'prosemirror-model'; | ||
import { TextSelection, NodeSelection, AllSelection } from 'prosemirror-state'; | ||
import { toggleMark, setBlockType } from 'prosemirror-commands'; | ||
import { ReplaceAroundStep } from 'prosemirror-transform'; | ||
import { sinkListItem, liftListItem } from 'prosemirror-schema-list'; | ||
@@ -298,2 +299,10 @@ import { schema } from './config/schema'; | ||
*/ | ||
export var toggleSubscript = toggleMark(schema.marks.subscript); | ||
/** | ||
* @hidden | ||
*/ | ||
export var toggleSuperscript = toggleMark(schema.marks.superscript); | ||
/** | ||
* @hidden | ||
*/ | ||
export var createLink = function (linkAttrs) { return function (state, dispatch) { | ||
@@ -385,1 +394,174 @@ if (isMarkActive(state, schema.marks.link)) { | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
var blockNodes = function (state) { | ||
var selection = state.selection; | ||
var from = selection.from, to = selection.to, $from = selection.$from; | ||
var result = []; | ||
if (selection.node) { | ||
if (selection.node.isBlock) { | ||
result.push(selection.node); | ||
} | ||
else if ($from.parent && $from.parent.isBlock) { | ||
result.push($from.parent); | ||
} | ||
} | ||
else { | ||
state.doc.nodesBetween(from, to, function (node) { | ||
if (node.isBlock) { | ||
result.push(node); | ||
} | ||
}); | ||
} | ||
return result; | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
var changeStyles = function (elementStyle, newStyle) { | ||
var styleToChange = newStyle.style; | ||
var regExp = newStyle.value; | ||
var newValue = newStyle.newValue; | ||
var styleMatches = []; | ||
if (elementStyle) { | ||
var splits = elementStyle.split(/\s*;\s*/).filter(function (s) { return s; }); | ||
var filtered = splits.filter(function (s) { | ||
if (!s.toLowerCase().trim().startsWith(styleToChange)) { | ||
return true; | ||
} | ||
var value = s.split(':')[1].trim(); | ||
if (regExp.test(value)) { | ||
styleMatches.push(value); | ||
return false; | ||
} | ||
return true; | ||
}); | ||
if (newValue) { | ||
filtered.push(styleToChange + ": " + newValue); | ||
} | ||
return { | ||
style: filtered.join('; ') + (filtered.length ? ';' : ''), | ||
changed: !!newValue || filtered.length !== splits.length, | ||
styleMatches: styleMatches | ||
}; | ||
} | ||
return { changed: false, styleMatches: styleMatches, style: null }; | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
var addStyles = function (node, stylesToApply) { | ||
var currentStyles = node.attrs.style, changedStyleResult = null, toChange = null; | ||
if (currentStyles) { | ||
stylesToApply.forEach(function (style) { | ||
toChange = { style: style.name, value: /^.+$/, newValue: style.value }; | ||
changedStyleResult = changeStyles(currentStyles, toChange); | ||
currentStyles = changedStyleResult.changed ? changedStyleResult.style : currentStyles; | ||
}); | ||
} | ||
var reducer = function (acc, curr) { | ||
return (acc && curr.value ? acc + ' ' : '') + curr.value ? curr.name + ": " + curr.value + ";" : ''; | ||
}; | ||
currentStyles = currentStyles || | ||
stylesToApply.reduce(reducer, ''); | ||
return Object.assign({}, node.attrs, { style: currentStyles || null }); | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
var canChangeType = function (stateDoc, pos, type) { | ||
var $pos = stateDoc.resolve(pos), index = $pos.index(); | ||
return $pos.parent.canReplaceWith(index, index + 1, type); | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
var changeBlockNode = function (state, dispatch, tr, node, nodeType, attrs) { | ||
var _a = state.selection, from = _a.from, to = _a.to; | ||
var applicable = false; | ||
state.doc.nodesBetween(from, to, function (currNode, pos) { | ||
if (applicable) { | ||
return false; | ||
} | ||
if (!currNode.isTextblock || currNode.hasMarkup(nodeType, attrs)) { | ||
return; | ||
} | ||
if (currNode.type === nodeType) { | ||
applicable = true; | ||
} | ||
else { | ||
var $pos = state.doc.resolve(pos), index = $pos.index(); | ||
applicable = $pos.parent.canReplaceWith(index, index + 1, nodeType); | ||
} | ||
}); | ||
if (!applicable) { | ||
return false; | ||
} | ||
if (dispatch) { | ||
// const tr = view.state.tr; | ||
// const tr = view.state.tr.setBlockType(from, to, nodeType, attrs); | ||
if (!nodeType.isTextblock) { | ||
throw new RangeError('Type given to setBlockType should be a textblock'); | ||
} | ||
var mapFrom_1 = tr.steps.length; | ||
tr.doc.nodesBetween(from, to, function (currNode, pos) { | ||
if (currNode.eq(node) && currNode.isTextblock && !currNode.hasMarkup(nodeType, attrs) && | ||
canChangeType(tr.doc, tr.mapping.slice(mapFrom_1).map(pos), nodeType)) { | ||
// Ensure all markup that isn't allowed in the new node type is cleared | ||
tr.clearIncompatible(tr.mapping.slice(mapFrom_1).map(pos, 1), nodeType); | ||
var mapping = tr.mapping.slice(mapFrom_1); | ||
var startM = mapping.map(pos, 1), endM = mapping.map(pos + currNode.nodeSize, 1); | ||
var slice = new Slice(Fragment.from(nodeType.create(attrs, null, currNode.marks)), 0, 0); | ||
tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, slice, 1, true)); | ||
return false; // this will skip the node children | ||
} | ||
}); | ||
// view.dispatch(tr.scrollIntoView()); | ||
} | ||
return true; | ||
}; | ||
/** | ||
* @hidden | ||
* Aligning block elements in the selection. | ||
* | ||
* @returns {boolean} - Returns true if any alignment is applied. | ||
*/ | ||
export var alignBlocks = function (actions) { return function (state, dispatch) { | ||
var blocks = blockNodes(state); | ||
var tr = state.tr; | ||
var result = false; | ||
blocks.forEach(function (node) { | ||
if (node.type.isTextblock) { | ||
var newAttrs = {}; | ||
var action = actions.find(function (n) { return n.node === node.type.name; }); | ||
if (action) { | ||
newAttrs = addStyles(node, action.style); | ||
} | ||
result = changeBlockNode(state, dispatch, tr, node, node.type, newAttrs) || result; | ||
} | ||
}); | ||
if (result) { | ||
dispatch(tr.scrollIntoView()); | ||
} | ||
return result; | ||
}; }; | ||
/** | ||
* @hidden | ||
* Checks if any block element in the selection is aligned. | ||
*/ | ||
export var isAligned = function (state, actions) { | ||
var blocks = blockNodes(state); | ||
var result = false; | ||
blocks.forEach(function (node) { | ||
if (!result && node.type.isTextblock && node.attrs.style) { | ||
var action = actions.find(function (a) { return a.node === node.type.name; }); | ||
if (action) { | ||
result = action.style.every(function (style) { | ||
return !!style.value && new RegExp(style.name + ":\\s?" + style.value, 'i').test(node.attrs.style); | ||
}); | ||
} | ||
} | ||
}); | ||
return result; | ||
}; |
@@ -23,9 +23,5 @@ /** | ||
*/ | ||
export var isEmpty = function (obj) { return Object.keys(obj).length === 0; }; | ||
/** | ||
* @hidden | ||
*/ | ||
export var removeEmptyEntries = function (obj) { | ||
export var removeEntries = function (obj, predicate) { | ||
return Object.keys(obj) | ||
.filter(function (key) { return obj[key] !== null && obj[key] !== undefined && obj[key] !== ''; }) | ||
.filter(function (key) { return predicate(key); }) | ||
.reduce(function (acc, curr) { | ||
@@ -39,2 +35,13 @@ return Object.assign(acc, (_a = {}, _a[curr] = obj[curr], _a)); | ||
*/ | ||
export var removeEmptyEntries = function (obj) { | ||
var predicate = function (key) { return obj[key] !== null && obj[key] !== undefined && obj[key] !== ''; }; | ||
return removeEntries(obj, predicate); | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
export var isEmpty = function (obj) { return Object.keys(obj).length === 0; }; | ||
/** | ||
* @hidden | ||
*/ | ||
export var isNullOrUndefined = function (value) { return value === undefined || value === null; }; | ||
@@ -41,0 +48,0 @@ /** |
@@ -15,6 +15,12 @@ /** | ||
outdent: 'indent-decrease', | ||
alignLeft: 'align-left', | ||
alignCenter: 'align-center', | ||
alignRight: 'align-right', | ||
alignJustify: 'align-justify', | ||
viewSource: 'html', | ||
undo: 'undo', | ||
redo: 'redo', | ||
insertImage: 'image' | ||
insertImage: 'image', | ||
subscript: 'sub-script', | ||
superscript: 'sup-script' | ||
}; |
import { undo, redo } from 'prosemirror-history'; | ||
import { schema } from './schema'; | ||
import { removeMark, toggleBold, toggleItalic, toggleUnderline, toggleStrikethrough, createLink, format, indent, outdent, getHTML, setHTML, insertImage } from '../prosemirror-utils'; | ||
import { alignLeftRules, alignCenterRules, alignRightRules, alignRemoveRules } from './align-rules'; | ||
import { removeMark, toggleBold, toggleItalic, toggleUnderline, toggleStrikethrough, alignBlocks, createLink, format, indent, outdent, getHTML, setHTML, insertImage, toggleSubscript, toggleSuperscript } from '../prosemirror-utils'; | ||
import { toggleOrderedList, toggleUnorderedList } from '../prosemirror-list-utils'; | ||
@@ -11,6 +12,12 @@ const inlineCommand = { | ||
underline: () => toggleUnderline, | ||
strikethrough: () => toggleStrikethrough | ||
strikethrough: () => toggleStrikethrough, | ||
subscript: () => toggleSubscript, | ||
superscript: () => toggleSuperscript | ||
}; | ||
const blockCommand = { | ||
format: (formatAttr) => format(formatAttr), | ||
alignLeft: () => alignBlocks(alignLeftRules), | ||
alignCenter: () => alignBlocks(alignCenterRules), | ||
alignRight: () => alignBlocks(alignRightRules), | ||
alignJustify: () => alignBlocks(alignRemoveRules), | ||
indent: () => indent, | ||
@@ -17,0 +24,0 @@ outdent: () => outdent, |
/** | ||
* @hidden | ||
*/ | ||
export declare type Marks = 'link' | 'em' | 'strong' | 'code' | 'underline' | 'strikethrough'; | ||
export declare type Marks = 'link' | 'em' | 'strong' | 'code' | 'underline' | 'strikethrough' | 'subscript' | 'superscript'; | ||
/** | ||
@@ -6,0 +6,0 @@ * @hidden |
import { Schema } from 'prosemirror-model'; | ||
import { serializeDOMAttrs, isEmpty, removeEmptyEntries } from '../util'; | ||
import { isEmpty, serializeDOMAttrs, removeEmptyEntries, removeEntries } from '../util'; | ||
const SLOT = 0; //https://prosemirror.net/docs/guide/#schema.serialization_and_parsing | ||
const commonAttributes = () => { | ||
return { | ||
style: { default: null }, | ||
class: { default: null }, | ||
id: { default: null } | ||
}; | ||
}; | ||
/** | ||
@@ -82,2 +89,20 @@ * @hidden | ||
toDOM: () => ['del', SLOT] | ||
}, | ||
// :: MarkSpec A subscript mark. Rendered as a `<sub>` element. | ||
// Parse rules also match `vertical-align: sub`. | ||
subscript: { | ||
parseDOM: [ | ||
{ tag: 'sub' }, | ||
{ style: 'vertical-align=sub' } | ||
], | ||
toDOM: () => ['sub', SLOT] | ||
}, | ||
// :: MarkSpec A superscript mark. Rendered as a `<sup>` element. | ||
// Parse rules also match `vertical-align: super`. | ||
superscript: { | ||
parseDOM: [ | ||
{ tag: 'sup' }, | ||
{ style: 'vertical-align=super' } | ||
], | ||
toDOM: () => ['sup', SLOT] | ||
} | ||
@@ -98,2 +123,3 @@ }; | ||
group: 'block', | ||
attrs: Object.assign({}, commonAttributes()), | ||
parseDOM: [{ | ||
@@ -109,5 +135,6 @@ tag: 'p', | ||
group: 'block', | ||
attrs: Object.assign({}, commonAttributes()), | ||
defining: true, | ||
parseDOM: [{ tag: 'blockquote' }], | ||
toDOM: () => ['blockquote', SLOT] | ||
toDOM: (node) => ['blockquote', removeEmptyEntries(node.attrs), SLOT] | ||
}, | ||
@@ -124,3 +151,3 @@ // :: NodeSpec A horizontal (`<hr>`) rule. | ||
heading: { | ||
attrs: { level: { default: 1 } }, | ||
attrs: Object.assign({ level: { default: 1 } }, commonAttributes()), | ||
content: 'inline*', | ||
@@ -137,3 +164,6 @@ group: 'block', | ||
], | ||
toDOM: (node) => ['h' + node.attrs.level, SLOT] | ||
toDOM: (node) => { | ||
const attrs = removeEntries(node.attrs, (key) => key !== 'level'); | ||
return ['h' + node.attrs.level, removeEmptyEntries(attrs), SLOT]; | ||
} | ||
}, | ||
@@ -164,8 +194,3 @@ // :: NodeSpec A code listing. Prevents marks or non-text inline | ||
inline: true, | ||
attrs: { | ||
src: {}, | ||
alt: { default: null }, | ||
width: { default: null }, | ||
height: { default: null } | ||
}, | ||
attrs: Object.assign({}, commonAttributes(), { src: {}, alt: { default: null }, width: { default: null }, height: { default: null } }), | ||
group: 'inline', | ||
@@ -194,6 +219,7 @@ draggable: true, | ||
listItem: { | ||
attrs: Object.assign({}, commonAttributes()), | ||
content: 'paragraph block*', | ||
marks: '_', | ||
parseDOM: [{ tag: 'li' }], | ||
toDOM: () => ['li', SLOT] | ||
toDOM: (node) => ['li', removeEmptyEntries(node.attrs), SLOT] | ||
}, | ||
@@ -200,0 +226,0 @@ // :: NodeSpec An ordered list. Represented as an `<ol>` element. |
@@ -16,6 +16,7 @@ import { Component, HostBinding, ViewChild, ContentChild, ViewContainerRef, Output, ElementRef, EventEmitter, forwardRef, Input } from '@angular/core'; | ||
import { editorCommands } from './config/commands'; | ||
import { alignRightRules, alignCenterRules, alignRemoveRules, alignLeftRules } from './config/align-rules'; | ||
import { LinkDialogComponent } from './dialogs/link-dialog.component'; | ||
import { SourceDialogComponent } from './dialogs/source-dialog.component'; | ||
import { isMarkActive, activeNodeName, canIndent, canOutdent, getHTML, createContentNode, hasSameMarkup, isInListOfType } from './prosemirror-utils'; | ||
import { ImageDialogComponent } from './dialogs/image-dialog.component'; | ||
import { isMarkActive, activeNodeName, canIndent, canOutdent, getHTML, createContentNode, hasSameMarkup, isInListOfType, isAligned } from './prosemirror-utils'; | ||
function updateToolBar({ state }) { | ||
@@ -29,2 +30,4 @@ return { | ||
link: isMarkActive(state, schema.marks.link), | ||
subscript: isMarkActive(state, schema.marks.subscript), | ||
superscript: isMarkActive(state, schema.marks.superscript), | ||
//nodes | ||
@@ -36,2 +39,6 @@ format: activeNodeName(state), | ||
outdent: canOutdent(state, schema.nodes.listItem), | ||
alignLeft: isAligned(state, alignLeftRules), | ||
alignCenter: isAligned(state, alignCenterRules), | ||
alignRight: isAligned(state, alignRightRules), | ||
alignJustify: isAligned(state, alignRemoveRules), | ||
//history | ||
@@ -38,0 +45,0 @@ undo: !undo(state), |
@@ -14,3 +14,3 @@ import { EditorState, Transaction } from 'prosemirror-state'; | ||
*/ | ||
export declare type EditorCommand = 'bold' | 'italic' | 'underline' | 'strikethrough' | 'createLink' | 'unlink' | 'insertImage' | 'insertOrderedList' | 'insertUnorderedList' | 'indent' | 'outdent' | 'justifyLeft' | 'justifyCenter' | 'justifyRight' | 'justifyFull' | 'format' | 'cleanFormat' | 'setHTML' | 'undo' | 'redo'; | ||
export declare type EditorCommand = 'bold' | 'italic' | 'underline' | 'strikethrough' | 'createLink' | 'unlink' | 'insertImage' | 'insertOrderedList' | 'insertUnorderedList' | 'indent' | 'outdent' | 'alignLeft' | 'alignCenter' | 'alignRight' | 'alignJustify' | 'format' | 'cleanFormat' | 'setHTML' | 'undo' | 'redo' | 'subscript' | 'superscript'; | ||
/** | ||
@@ -17,0 +17,0 @@ * The list of the dialog names that are accepted by the `openDialog` method. |
import { MarkType, NodeType, ResolvedPos } from 'prosemirror-model'; | ||
import { EditorState } from 'prosemirror-state'; | ||
import { AlignRule } from './config/align-rules'; | ||
import { LinkData } from './dialogs/link-dialog.component'; | ||
import { Command } from './models/commands'; | ||
import { Command, DispatchFn } from './models/commands'; | ||
import { ImageData } from './dialogs/image-dialog.component'; | ||
@@ -83,2 +84,10 @@ /** | ||
*/ | ||
export declare const toggleSubscript: any; | ||
/** | ||
* @hidden | ||
*/ | ||
export declare const toggleSuperscript: any; | ||
/** | ||
* @hidden | ||
*/ | ||
export declare const createLink: (linkAttrs: LinkData) => Command; | ||
@@ -131,1 +140,13 @@ /** | ||
export declare const hasSameMarkup: (dom1: string, dom2: string) => boolean; | ||
/** | ||
* @hidden | ||
* Aligning block elements in the selection. | ||
* | ||
* @returns {boolean} - Returns true if any alignment is applied. | ||
*/ | ||
export declare const alignBlocks: (actions: AlignRule[]) => (state: any, dispatch: DispatchFn) => boolean; | ||
/** | ||
* @hidden | ||
* Checks if any block element in the selection is aligned. | ||
*/ | ||
export declare const isAligned: (state: any, actions: AlignRule[]) => boolean; |
@@ -1,4 +0,5 @@ | ||
import { Node, DOMParser, DOMSerializer, Fragment } from 'prosemirror-model'; | ||
import { TextSelection, AllSelection, NodeSelection } from 'prosemirror-state'; | ||
import { Node, DOMParser, DOMSerializer, Fragment, Slice } from 'prosemirror-model'; | ||
import { TextSelection, NodeSelection, AllSelection } from 'prosemirror-state'; | ||
import { toggleMark, setBlockType } from 'prosemirror-commands'; | ||
import { ReplaceAroundStep } from 'prosemirror-transform'; | ||
import { sinkListItem, liftListItem } from 'prosemirror-schema-list'; | ||
@@ -293,2 +294,10 @@ import { schema } from './config/schema'; | ||
*/ | ||
export const toggleSubscript = toggleMark(schema.marks.subscript); | ||
/** | ||
* @hidden | ||
*/ | ||
export const toggleSuperscript = toggleMark(schema.marks.superscript); | ||
/** | ||
* @hidden | ||
*/ | ||
export const createLink = (linkAttrs) => (state, dispatch) => { | ||
@@ -377,1 +386,172 @@ if (isMarkActive(state, schema.marks.link)) { | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
const blockNodes = (state) => { | ||
const selection = state.selection; | ||
let { from, to, $from } = selection; | ||
const result = []; | ||
if (selection.node) { | ||
if (selection.node.isBlock) { | ||
result.push(selection.node); | ||
} | ||
else if ($from.parent && $from.parent.isBlock) { | ||
result.push($from.parent); | ||
} | ||
} | ||
else { | ||
state.doc.nodesBetween(from, to, node => { | ||
if (node.isBlock) { | ||
result.push(node); | ||
} | ||
}); | ||
} | ||
return result; | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
const changeStyles = (elementStyle, newStyle) => { | ||
const styleToChange = newStyle.style; | ||
const regExp = newStyle.value; | ||
const newValue = newStyle.newValue; | ||
const styleMatches = []; | ||
if (elementStyle) { | ||
const splits = elementStyle.split(/\s*;\s*/).filter(s => s); | ||
const filtered = splits.filter(s => { | ||
if (!s.toLowerCase().trim().startsWith(styleToChange)) { | ||
return true; | ||
} | ||
const value = s.split(':')[1].trim(); | ||
if (regExp.test(value)) { | ||
styleMatches.push(value); | ||
return false; | ||
} | ||
return true; | ||
}); | ||
if (newValue) { | ||
filtered.push(`${styleToChange}: ${newValue}`); | ||
} | ||
return { | ||
style: filtered.join('; ') + (filtered.length ? ';' : ''), | ||
changed: !!newValue || filtered.length !== splits.length, | ||
styleMatches | ||
}; | ||
} | ||
return { changed: false, styleMatches, style: null }; | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
const addStyles = (node, stylesToApply) => { | ||
let currentStyles = node.attrs.style, changedStyleResult = null, toChange = null; | ||
if (currentStyles) { | ||
stylesToApply.forEach(style => { | ||
toChange = { style: style.name, value: /^.+$/, newValue: style.value }; | ||
changedStyleResult = changeStyles(currentStyles, toChange); | ||
currentStyles = changedStyleResult.changed ? changedStyleResult.style : currentStyles; | ||
}); | ||
} | ||
const reducer = (acc, curr) => (acc && curr.value ? acc + ' ' : '') + curr.value ? `${curr.name}: ${curr.value};` : ''; | ||
currentStyles = currentStyles || | ||
stylesToApply.reduce(reducer, ''); | ||
return Object.assign({}, node.attrs, { style: currentStyles || null }); | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
const canChangeType = (stateDoc, pos, type) => { | ||
let $pos = stateDoc.resolve(pos), index = $pos.index(); | ||
return $pos.parent.canReplaceWith(index, index + 1, type); | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
const changeBlockNode = (state, dispatch, tr, node, nodeType, attrs) => { | ||
let { from, to } = state.selection; | ||
let applicable = false; | ||
state.doc.nodesBetween(from, to, (currNode, pos) => { | ||
if (applicable) { | ||
return false; | ||
} | ||
if (!currNode.isTextblock || currNode.hasMarkup(nodeType, attrs)) { | ||
return; | ||
} | ||
if (currNode.type === nodeType) { | ||
applicable = true; | ||
} | ||
else { | ||
let $pos = state.doc.resolve(pos), index = $pos.index(); | ||
applicable = $pos.parent.canReplaceWith(index, index + 1, nodeType); | ||
} | ||
}); | ||
if (!applicable) { | ||
return false; | ||
} | ||
if (dispatch) { | ||
// const tr = view.state.tr; | ||
// const tr = view.state.tr.setBlockType(from, to, nodeType, attrs); | ||
if (!nodeType.isTextblock) { | ||
throw new RangeError('Type given to setBlockType should be a textblock'); | ||
} | ||
let mapFrom = tr.steps.length; | ||
tr.doc.nodesBetween(from, to, (currNode, pos) => { | ||
if (currNode.eq(node) && currNode.isTextblock && !currNode.hasMarkup(nodeType, attrs) && | ||
canChangeType(tr.doc, tr.mapping.slice(mapFrom).map(pos), nodeType)) { | ||
// Ensure all markup that isn't allowed in the new node type is cleared | ||
tr.clearIncompatible(tr.mapping.slice(mapFrom).map(pos, 1), nodeType); | ||
let mapping = tr.mapping.slice(mapFrom); | ||
let startM = mapping.map(pos, 1), endM = mapping.map(pos + currNode.nodeSize, 1); | ||
let slice = new Slice(Fragment.from(nodeType.create(attrs, null, currNode.marks)), 0, 0); | ||
tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, slice, 1, true)); | ||
return false; // this will skip the node children | ||
} | ||
}); | ||
// view.dispatch(tr.scrollIntoView()); | ||
} | ||
return true; | ||
}; | ||
/** | ||
* @hidden | ||
* Aligning block elements in the selection. | ||
* | ||
* @returns {boolean} - Returns true if any alignment is applied. | ||
*/ | ||
export const alignBlocks = (actions) => (state, dispatch) => { | ||
const blocks = blockNodes(state); | ||
const tr = state.tr; | ||
let result = false; | ||
blocks.forEach(node => { | ||
if (node.type.isTextblock) { | ||
let newAttrs = {}; | ||
const action = actions.find(n => n.node === node.type.name); | ||
if (action) { | ||
newAttrs = addStyles(node, action.style); | ||
} | ||
result = changeBlockNode(state, dispatch, tr, node, node.type, newAttrs) || result; | ||
} | ||
}); | ||
if (result) { | ||
dispatch(tr.scrollIntoView()); | ||
} | ||
return result; | ||
}; | ||
/** | ||
* @hidden | ||
* Checks if any block element in the selection is aligned. | ||
*/ | ||
export const isAligned = (state, actions) => { | ||
const blocks = blockNodes(state); | ||
let result = false; | ||
blocks.forEach(node => { | ||
if (!result && node.type.isTextblock && node.attrs.style) { | ||
const action = actions.find(a => a.node === node.type.name); | ||
if (action) { | ||
result = action.style.every(style => { | ||
return !!style.value && new RegExp(`${style.name}:\\s?${style.value}`, 'i').test(node.attrs.style); | ||
}); | ||
} | ||
} | ||
}); | ||
return result; | ||
}; |
@@ -12,10 +12,18 @@ /** | ||
*/ | ||
export declare const isEmpty: (obj: Object) => boolean; | ||
export declare const removeEntries: (obj: Object, predicate: (key: string) => boolean) => { | ||
[key: string]: string; | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
export declare const removeEmptyEntries: (obj: Object) => {}; | ||
export declare const removeEmptyEntries: (obj: Object) => { | ||
[key: string]: string; | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
export declare const isEmpty: (obj: Object) => boolean; | ||
/** | ||
* @hidden | ||
*/ | ||
export declare const isNullOrUndefined: (value: any) => boolean; | ||
@@ -22,0 +30,0 @@ /** |
@@ -18,12 +18,19 @@ /** | ||
*/ | ||
export const isEmpty = (obj) => Object.keys(obj).length === 0; | ||
export const removeEntries = (obj, predicate) => Object.keys(obj) | ||
.filter(key => predicate(key)) | ||
.reduce((acc, curr) => Object.assign(acc, { [curr]: obj[curr] }), {}); | ||
/** | ||
* @hidden | ||
*/ | ||
export const removeEmptyEntries = (obj) => Object.keys(obj) | ||
.filter(key => obj[key] !== null && obj[key] !== undefined && obj[key] !== '') | ||
.reduce((acc, curr) => Object.assign(acc, { [curr]: obj[curr] }), {}); | ||
export const removeEmptyEntries = (obj) => { | ||
const predicate = (key) => obj[key] !== null && obj[key] !== undefined && obj[key] !== ''; | ||
return removeEntries(obj, predicate); | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
export const isEmpty = (obj) => Object.keys(obj).length === 0; | ||
/** | ||
* @hidden | ||
*/ | ||
export const isNullOrUndefined = (value) => value === undefined || value === null; | ||
@@ -30,0 +37,0 @@ /** |
@@ -17,6 +17,12 @@ "use strict"; | ||
outdent: 'indent-decrease', | ||
alignLeft: 'align-left', | ||
alignCenter: 'align-center', | ||
alignRight: 'align-right', | ||
alignJustify: 'align-justify', | ||
viewSource: 'html', | ||
undo: 'undo', | ||
redo: 'redo', | ||
insertImage: 'image' | ||
insertImage: 'image', | ||
subscript: 'sub-script', | ||
superscript: 'sup-script' | ||
}; |
@@ -5,2 +5,3 @@ "use strict"; | ||
var schema_1 = require("./schema"); | ||
var align_rules_1 = require("./align-rules"); | ||
var prosemirror_utils_1 = require("../prosemirror-utils"); | ||
@@ -14,6 +15,12 @@ var prosemirror_list_utils_1 = require("../prosemirror-list-utils"); | ||
underline: function () { return prosemirror_utils_1.toggleUnderline; }, | ||
strikethrough: function () { return prosemirror_utils_1.toggleStrikethrough; } | ||
strikethrough: function () { return prosemirror_utils_1.toggleStrikethrough; }, | ||
subscript: function () { return prosemirror_utils_1.toggleSubscript; }, | ||
superscript: function () { return prosemirror_utils_1.toggleSuperscript; } | ||
}; | ||
var blockCommand = { | ||
format: function (formatAttr) { return prosemirror_utils_1.format(formatAttr); }, | ||
alignLeft: function () { return prosemirror_utils_1.alignBlocks(align_rules_1.alignLeftRules); }, | ||
alignCenter: function () { return prosemirror_utils_1.alignBlocks(align_rules_1.alignCenterRules); }, | ||
alignRight: function () { return prosemirror_utils_1.alignBlocks(align_rules_1.alignRightRules); }, | ||
alignJustify: function () { return prosemirror_utils_1.alignBlocks(align_rules_1.alignRemoveRules); }, | ||
indent: function () { return prosemirror_utils_1.indent; }, | ||
@@ -20,0 +27,0 @@ outdent: function () { return prosemirror_utils_1.outdent; }, |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var tslib_1 = require("tslib"); | ||
var prosemirror_model_1 = require("prosemirror-model"); | ||
var util_1 = require("../util"); | ||
var SLOT = 0; //https://prosemirror.net/docs/guide/#schema.serialization_and_parsing | ||
var commonAttributes = function () { | ||
return { | ||
style: { default: null }, | ||
class: { default: null }, | ||
id: { default: null } | ||
}; | ||
}; | ||
/** | ||
@@ -84,2 +92,20 @@ * @hidden | ||
toDOM: function () { return ['del', SLOT]; } | ||
}, | ||
// :: MarkSpec A subscript mark. Rendered as a `<sub>` element. | ||
// Parse rules also match `vertical-align: sub`. | ||
subscript: { | ||
parseDOM: [ | ||
{ tag: 'sub' }, | ||
{ style: 'vertical-align=sub' } | ||
], | ||
toDOM: function () { return ['sub', SLOT]; } | ||
}, | ||
// :: MarkSpec A superscript mark. Rendered as a `<sup>` element. | ||
// Parse rules also match `vertical-align: super`. | ||
superscript: { | ||
parseDOM: [ | ||
{ tag: 'sup' }, | ||
{ style: 'vertical-align=super' } | ||
], | ||
toDOM: function () { return ['sup', SLOT]; } | ||
} | ||
@@ -100,2 +126,3 @@ }; | ||
group: 'block', | ||
attrs: tslib_1.__assign({}, commonAttributes()), | ||
parseDOM: [{ | ||
@@ -111,5 +138,6 @@ tag: 'p', | ||
group: 'block', | ||
attrs: tslib_1.__assign({}, commonAttributes()), | ||
defining: true, | ||
parseDOM: [{ tag: 'blockquote' }], | ||
toDOM: function () { return ['blockquote', SLOT]; } | ||
toDOM: function (node) { return ['blockquote', util_1.removeEmptyEntries(node.attrs), SLOT]; } | ||
}, | ||
@@ -126,3 +154,3 @@ // :: NodeSpec A horizontal (`<hr>`) rule. | ||
heading: { | ||
attrs: { level: { default: 1 } }, | ||
attrs: tslib_1.__assign({ level: { default: 1 } }, commonAttributes()), | ||
content: 'inline*', | ||
@@ -139,3 +167,6 @@ group: 'block', | ||
], | ||
toDOM: function (node) { return ['h' + node.attrs.level, SLOT]; } | ||
toDOM: function (node) { | ||
var attrs = util_1.removeEntries(node.attrs, function (key) { return key !== 'level'; }); | ||
return ['h' + node.attrs.level, util_1.removeEmptyEntries(attrs), SLOT]; | ||
} | ||
}, | ||
@@ -166,8 +197,3 @@ // :: NodeSpec A code listing. Prevents marks or non-text inline | ||
inline: true, | ||
attrs: { | ||
src: {}, | ||
alt: { default: null }, | ||
width: { default: null }, | ||
height: { default: null } | ||
}, | ||
attrs: tslib_1.__assign({}, commonAttributes(), { src: {}, alt: { default: null }, width: { default: null }, height: { default: null } }), | ||
group: 'inline', | ||
@@ -196,6 +222,7 @@ draggable: true, | ||
listItem: { | ||
attrs: tslib_1.__assign({}, commonAttributes()), | ||
content: 'paragraph block*', | ||
marks: '_', | ||
parseDOM: [{ tag: 'li' }], | ||
toDOM: function () { return ['li', SLOT]; } | ||
toDOM: function (node) { return ['li', util_1.removeEmptyEntries(node.attrs), SLOT]; } | ||
}, | ||
@@ -202,0 +229,0 @@ // :: NodeSpec An ordered list. Represented as an `<ol>` element. |
@@ -18,6 +18,7 @@ "use strict"; | ||
var commands_1 = require("./config/commands"); | ||
var align_rules_1 = require("./config/align-rules"); | ||
var link_dialog_component_1 = require("./dialogs/link-dialog.component"); | ||
var source_dialog_component_1 = require("./dialogs/source-dialog.component"); | ||
var image_dialog_component_1 = require("./dialogs/image-dialog.component"); | ||
var prosemirror_utils_1 = require("./prosemirror-utils"); | ||
var image_dialog_component_1 = require("./dialogs/image-dialog.component"); | ||
function updateToolBar(_a) { | ||
@@ -32,2 +33,4 @@ var state = _a.state; | ||
link: prosemirror_utils_1.isMarkActive(state, schema_1.schema.marks.link), | ||
subscript: prosemirror_utils_1.isMarkActive(state, schema_1.schema.marks.subscript), | ||
superscript: prosemirror_utils_1.isMarkActive(state, schema_1.schema.marks.superscript), | ||
//nodes | ||
@@ -39,2 +42,6 @@ format: prosemirror_utils_1.activeNodeName(state), | ||
outdent: prosemirror_utils_1.canOutdent(state, schema_1.schema.nodes.listItem), | ||
alignLeft: prosemirror_utils_1.isAligned(state, align_rules_1.alignLeftRules), | ||
alignCenter: prosemirror_utils_1.isAligned(state, align_rules_1.alignCenterRules), | ||
alignRight: prosemirror_utils_1.isAligned(state, align_rules_1.alignRightRules), | ||
alignJustify: prosemirror_utils_1.isAligned(state, align_rules_1.alignRemoveRules), | ||
//history | ||
@@ -41,0 +48,0 @@ undo: !prosemirror_history_1.undo(state), |
@@ -6,2 +6,3 @@ "use strict"; | ||
var prosemirror_commands_1 = require("prosemirror-commands"); | ||
var prosemirror_transform_1 = require("prosemirror-transform"); | ||
var prosemirror_schema_list_1 = require("prosemirror-schema-list"); | ||
@@ -310,2 +311,10 @@ var schema_1 = require("./config/schema"); | ||
*/ | ||
exports.toggleSubscript = prosemirror_commands_1.toggleMark(schema_1.schema.marks.subscript); | ||
/** | ||
* @hidden | ||
*/ | ||
exports.toggleSuperscript = prosemirror_commands_1.toggleMark(schema_1.schema.marks.superscript); | ||
/** | ||
* @hidden | ||
*/ | ||
exports.createLink = function (linkAttrs) { return function (state, dispatch) { | ||
@@ -397,1 +406,174 @@ if (isMarkActive(state, schema_1.schema.marks.link)) { | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
var blockNodes = function (state) { | ||
var selection = state.selection; | ||
var from = selection.from, to = selection.to, $from = selection.$from; | ||
var result = []; | ||
if (selection.node) { | ||
if (selection.node.isBlock) { | ||
result.push(selection.node); | ||
} | ||
else if ($from.parent && $from.parent.isBlock) { | ||
result.push($from.parent); | ||
} | ||
} | ||
else { | ||
state.doc.nodesBetween(from, to, function (node) { | ||
if (node.isBlock) { | ||
result.push(node); | ||
} | ||
}); | ||
} | ||
return result; | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
var changeStyles = function (elementStyle, newStyle) { | ||
var styleToChange = newStyle.style; | ||
var regExp = newStyle.value; | ||
var newValue = newStyle.newValue; | ||
var styleMatches = []; | ||
if (elementStyle) { | ||
var splits = elementStyle.split(/\s*;\s*/).filter(function (s) { return s; }); | ||
var filtered = splits.filter(function (s) { | ||
if (!s.toLowerCase().trim().startsWith(styleToChange)) { | ||
return true; | ||
} | ||
var value = s.split(':')[1].trim(); | ||
if (regExp.test(value)) { | ||
styleMatches.push(value); | ||
return false; | ||
} | ||
return true; | ||
}); | ||
if (newValue) { | ||
filtered.push(styleToChange + ": " + newValue); | ||
} | ||
return { | ||
style: filtered.join('; ') + (filtered.length ? ';' : ''), | ||
changed: !!newValue || filtered.length !== splits.length, | ||
styleMatches: styleMatches | ||
}; | ||
} | ||
return { changed: false, styleMatches: styleMatches, style: null }; | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
var addStyles = function (node, stylesToApply) { | ||
var currentStyles = node.attrs.style, changedStyleResult = null, toChange = null; | ||
if (currentStyles) { | ||
stylesToApply.forEach(function (style) { | ||
toChange = { style: style.name, value: /^.+$/, newValue: style.value }; | ||
changedStyleResult = changeStyles(currentStyles, toChange); | ||
currentStyles = changedStyleResult.changed ? changedStyleResult.style : currentStyles; | ||
}); | ||
} | ||
var reducer = function (acc, curr) { | ||
return (acc && curr.value ? acc + ' ' : '') + curr.value ? curr.name + ": " + curr.value + ";" : ''; | ||
}; | ||
currentStyles = currentStyles || | ||
stylesToApply.reduce(reducer, ''); | ||
return Object.assign({}, node.attrs, { style: currentStyles || null }); | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
var canChangeType = function (stateDoc, pos, type) { | ||
var $pos = stateDoc.resolve(pos), index = $pos.index(); | ||
return $pos.parent.canReplaceWith(index, index + 1, type); | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
var changeBlockNode = function (state, dispatch, tr, node, nodeType, attrs) { | ||
var _a = state.selection, from = _a.from, to = _a.to; | ||
var applicable = false; | ||
state.doc.nodesBetween(from, to, function (currNode, pos) { | ||
if (applicable) { | ||
return false; | ||
} | ||
if (!currNode.isTextblock || currNode.hasMarkup(nodeType, attrs)) { | ||
return; | ||
} | ||
if (currNode.type === nodeType) { | ||
applicable = true; | ||
} | ||
else { | ||
var $pos = state.doc.resolve(pos), index = $pos.index(); | ||
applicable = $pos.parent.canReplaceWith(index, index + 1, nodeType); | ||
} | ||
}); | ||
if (!applicable) { | ||
return false; | ||
} | ||
if (dispatch) { | ||
// const tr = view.state.tr; | ||
// const tr = view.state.tr.setBlockType(from, to, nodeType, attrs); | ||
if (!nodeType.isTextblock) { | ||
throw new RangeError('Type given to setBlockType should be a textblock'); | ||
} | ||
var mapFrom_1 = tr.steps.length; | ||
tr.doc.nodesBetween(from, to, function (currNode, pos) { | ||
if (currNode.eq(node) && currNode.isTextblock && !currNode.hasMarkup(nodeType, attrs) && | ||
canChangeType(tr.doc, tr.mapping.slice(mapFrom_1).map(pos), nodeType)) { | ||
// Ensure all markup that isn't allowed in the new node type is cleared | ||
tr.clearIncompatible(tr.mapping.slice(mapFrom_1).map(pos, 1), nodeType); | ||
var mapping = tr.mapping.slice(mapFrom_1); | ||
var startM = mapping.map(pos, 1), endM = mapping.map(pos + currNode.nodeSize, 1); | ||
var slice = new prosemirror_model_1.Slice(prosemirror_model_1.Fragment.from(nodeType.create(attrs, null, currNode.marks)), 0, 0); | ||
tr.step(new prosemirror_transform_1.ReplaceAroundStep(startM, endM, startM + 1, endM - 1, slice, 1, true)); | ||
return false; // this will skip the node children | ||
} | ||
}); | ||
// view.dispatch(tr.scrollIntoView()); | ||
} | ||
return true; | ||
}; | ||
/** | ||
* @hidden | ||
* Aligning block elements in the selection. | ||
* | ||
* @returns {boolean} - Returns true if any alignment is applied. | ||
*/ | ||
exports.alignBlocks = function (actions) { return function (state, dispatch) { | ||
var blocks = blockNodes(state); | ||
var tr = state.tr; | ||
var result = false; | ||
blocks.forEach(function (node) { | ||
if (node.type.isTextblock) { | ||
var newAttrs = {}; | ||
var action = actions.find(function (n) { return n.node === node.type.name; }); | ||
if (action) { | ||
newAttrs = addStyles(node, action.style); | ||
} | ||
result = changeBlockNode(state, dispatch, tr, node, node.type, newAttrs) || result; | ||
} | ||
}); | ||
if (result) { | ||
dispatch(tr.scrollIntoView()); | ||
} | ||
return result; | ||
}; }; | ||
/** | ||
* @hidden | ||
* Checks if any block element in the selection is aligned. | ||
*/ | ||
exports.isAligned = function (state, actions) { | ||
var blocks = blockNodes(state); | ||
var result = false; | ||
blocks.forEach(function (node) { | ||
if (!result && node.type.isTextblock && node.attrs.style) { | ||
var action = actions.find(function (a) { return a.node === node.type.name; }); | ||
if (action) { | ||
result = action.style.every(function (style) { | ||
return !!style.value && new RegExp(style.name + ":\\s?" + style.value, 'i').test(node.attrs.style); | ||
}); | ||
} | ||
} | ||
}); | ||
return result; | ||
}; |
@@ -26,9 +26,5 @@ "use strict"; | ||
*/ | ||
exports.isEmpty = function (obj) { return Object.keys(obj).length === 0; }; | ||
/** | ||
* @hidden | ||
*/ | ||
exports.removeEmptyEntries = function (obj) { | ||
exports.removeEntries = function (obj, predicate) { | ||
return Object.keys(obj) | ||
.filter(function (key) { return obj[key] !== null && obj[key] !== undefined && obj[key] !== ''; }) | ||
.filter(function (key) { return predicate(key); }) | ||
.reduce(function (acc, curr) { | ||
@@ -42,2 +38,13 @@ return Object.assign(acc, (_a = {}, _a[curr] = obj[curr], _a)); | ||
*/ | ||
exports.removeEmptyEntries = function (obj) { | ||
var predicate = function (key) { return obj[key] !== null && obj[key] !== undefined && obj[key] !== ''; }; | ||
return exports.removeEntries(obj, predicate); | ||
}; | ||
/** | ||
* @hidden | ||
*/ | ||
exports.isEmpty = function (obj) { return Object.keys(obj).length === 0; }; | ||
/** | ||
* @hidden | ||
*/ | ||
exports.isNullOrUndefined = function (value) { return value === undefined || value === null; }; | ||
@@ -44,0 +51,0 @@ /** |
@@ -6,3 +6,3 @@ { | ||
"license": "SEE LICENSE IN LICENSE.md", | ||
"version": "0.3.0-dev.201902061710", | ||
"version": "0.3.0-dev.201902121457", | ||
"main": "dist/npm/index.js", | ||
@@ -9,0 +9,0 @@ "module": "dist/es/index.js", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
807566
100
7564