OXIESEC PANEL
- Current Dir:
/
/
var
/
www
/
reader
/
_backup
/
tinymce
/
tinymce
/
src
/
core
/
main
/
ts
/
keyboard
Server IP: 139.59.38.164
Upload:
Create Dir:
Name
Size
Modified
Perms
📁
..
-
02/20/2020 05:44:43 AM
rwxr-xr-x
📄
ArrowKeys.ts
2.28 KB
02/20/2020 05:43:50 AM
rw-r--r--
📄
BoundaryCaret.ts
2.59 KB
02/20/2020 05:43:50 AM
rw-r--r--
📄
BoundaryLocation.ts
6.56 KB
02/20/2020 05:43:51 AM
rw-r--r--
📄
BoundarySelection.ts
4.54 KB
02/20/2020 05:43:52 AM
rw-r--r--
📄
CefNavigation.ts
9.07 KB
02/20/2020 05:43:52 AM
rw-r--r--
📄
CefUtils.ts
2.54 KB
02/20/2020 05:43:53 AM
rw-r--r--
📄
ContentEndpointNavigation.ts
2.99 KB
02/20/2020 05:43:54 AM
rw-r--r--
📄
DeleteBackspaceKeys.ts
3.49 KB
02/20/2020 05:43:54 AM
rw-r--r--
📄
EnterKey.ts
1.29 KB
02/20/2020 05:43:55 AM
rw-r--r--
📄
FormatShortcuts.ts
886 bytes
02/20/2020 05:43:55 AM
rw-r--r--
📄
HomeEndKeys.ts
980 bytes
02/20/2020 05:43:56 AM
rw-r--r--
📄
InlineUtils.ts
3.26 KB
02/20/2020 05:43:56 AM
rw-r--r--
📄
InputKeys.ts
1.55 KB
02/20/2020 05:43:57 AM
rw-r--r--
📄
InsertSpace.ts
2.3 KB
02/20/2020 05:43:57 AM
rw-r--r--
📄
KeyboardOverrides.ts
1011 bytes
02/20/2020 05:43:58 AM
rw-r--r--
📄
MatchKeys.ts
1.64 KB
02/20/2020 05:43:58 AM
rw-r--r--
📄
Nbsps.ts
5.95 KB
02/20/2020 05:43:59 AM
rw-r--r--
📄
SpaceKey.ts
1 KB
02/20/2020 05:43:59 AM
rw-r--r--
📄
TableNavigation.ts
6.86 KB
02/20/2020 05:44:00 AM
rw-r--r--
Editing: Nbsps.ts
Close
/** * Copyright (c) Tiny Technologies, Inc. All rights reserved. * Licensed under the LGPL or a commercial license. * For LGPL see License.txt in the project root for license information. * For commercial licenses see https://www.tiny.cloud/ */ import { Text } from '@ephox/dom-globals'; import { Strings, Option, Arr } from '@ephox/katamari'; import { Element, PredicateFind, Node, Css } from '@ephox/sugar'; import { CaretPosition } from '../caret/CaretPosition'; import Editor from '../api/Editor'; import NodeType from '../dom/NodeType'; import Parents from '../dom/Parents'; import * as ElementType from '../dom/ElementType'; import { getElementFromPosition } from '../caret/CaretUtils'; import CaretFinder from '../caret/CaretFinder'; import { isAtStartOfBlock, isAtEndOfBlock } from '../caret/BlockBoundary'; import { isNbsp, isContent } from '../text/CharType'; import { isAfterBr, isBeforeBr } from '../caret/CaretBr'; import { isAfterSpace, isBeforeSpace } from '../caret/CaretPositionPredicates'; const nbsp = '\u00a0'; const isInMiddleOfText = (pos: CaretPosition) => CaretPosition.isTextPosition(pos) && !pos.isAtStart() && !pos.isAtEnd(); const getClosestBlock = (root: Element, pos: CaretPosition): Element => { const parentBlocks = Arr.filter(Parents.parentsAndSelf(Element.fromDom(pos.container()), root), ElementType.isBlock); return Arr.head(parentBlocks).getOr(root); }; const hasSpaceBefore = (root: Element, pos: CaretPosition): boolean => { if (isInMiddleOfText(pos)) { return isAfterSpace(pos); } else { return isAfterSpace(pos) || CaretFinder.prevPosition(getClosestBlock(root, pos).dom(), pos).exists(isAfterSpace); } }; const hasSpaceAfter = (root: Element, pos: CaretPosition): boolean => { if (isInMiddleOfText(pos)) { return isBeforeSpace(pos); } else { return isBeforeSpace(pos) || CaretFinder.nextPosition(getClosestBlock(root, pos).dom(), pos).exists(isBeforeSpace); } }; const isPreValue = (value: string) => Arr.contains([ 'pre', 'pre-line', 'pre-wrap' ], value); const isInPre = (pos: CaretPosition) => { return getElementFromPosition(pos) .bind((elm) => PredicateFind.closest(elm, Node.isElement)) .exists((elm) => isPreValue(Css.get(elm, 'white-space'))); }; const isAtBeginningOfBody = (root: Element, pos: CaretPosition) => CaretFinder.prevPosition(root.dom(), pos).isNone(); const isAtEndOfBody = (root: Element, pos: CaretPosition) => CaretFinder.nextPosition(root.dom(), pos).isNone(); const isAtLineBoundary = (root: Element, pos: CaretPosition) => { return ( isAtBeginningOfBody(root, pos) || isAtEndOfBody(root, pos) || isAtStartOfBlock(root, pos) || isAtEndOfBlock(root, pos) || isAfterBr(root, pos) || isBeforeBr(root, pos) ); }; const needsToHaveNbsp = (root: Element, pos: CaretPosition) => { if (isInPre(pos)) { return false; } else { return isAtLineBoundary(root, pos) || hasSpaceBefore(root, pos) || hasSpaceAfter(root, pos); } }; const needsToBeNbspLeft = (root: Element, pos: CaretPosition) => { if (isInPre(pos)) { return false; } else { return isAtStartOfBlock(root, pos) || isAfterBr(root, pos) || hasSpaceBefore(root, pos); } }; const leanRight = (pos: CaretPosition): CaretPosition => { const container = pos.container(); const offset = pos.offset(); if (NodeType.isText(container) && offset < container.data.length) { return CaretPosition(container, offset + 1); } else { return pos; } }; const needsToBeNbspRight = (root: Element, pos: CaretPosition) => { const afterPos = leanRight(pos); if (isInPre(afterPos)) { return false; } else { return isAtEndOfBlock(root, afterPos) || isBeforeBr(root, afterPos) || hasSpaceAfter(root, afterPos); } }; const needsToBeNbsp = (root: Element, pos: CaretPosition) => { return needsToBeNbspLeft(root, pos) || needsToBeNbspRight(root, pos); }; const isNbspAt = (text: string, offset: number) => { return isNbsp(text.charAt(offset)); }; const hasNbsp = (pos: CaretPosition) => { const container = pos.container(); return NodeType.isText(container) && Strings.contains(container.data, nbsp); }; const normalizeNbspMiddle = (text: string): string => { return Arr.map(text.split(''), (chr, i, chars) => { if (isNbsp(chr) && i > 0 && i < chars.length - 1 && isContent(chars[i - 1]) && isContent(chars[i + 1])) { return ' '; } else { return chr; } }).join(''); }; const normalizeNbspAtStart = (root: Element, node: Text): boolean => { const text = node.data; const firstPos = CaretPosition(node, 0); if (isNbspAt(text, 0) && !needsToBeNbsp(root, firstPos)) { node.data = ' ' + text.slice(1); return true; } else { return false; } }; const normalizeNbspInMiddleOfTextNode = (node: Text): boolean => { const text = node.data; const newText = normalizeNbspMiddle(text); if (newText !== text) { node.data = newText; return true; } else { return false; } }; const normalizeNbspAtEnd = (root: Element, node: Text): boolean => { const text = node.data; const lastPos = CaretPosition(node, text.length - 1); if (isNbspAt(text, text.length - 1) && !needsToBeNbsp(root, lastPos)) { node.data = text.slice(0, -1) + ' '; return true; } else { return false; } }; const normalizeNbsps = (root: Element, pos: CaretPosition): Option<CaretPosition> => { return Option.some(pos).filter(hasNbsp).bind((pos) => { const container = pos.container() as Text; const normalized = normalizeNbspAtStart(root, container) || normalizeNbspInMiddleOfTextNode(container) || normalizeNbspAtEnd(root, container); return normalized ? Option.some(pos) : Option.none(); }); }; const normalizeNbspsInEditor = (editor: Editor) => { const root = Element.fromDom(editor.getBody()); if (editor.selection.isCollapsed()) { normalizeNbsps(root, CaretPosition.fromRangeStart(editor.selection.getRng())).each((pos) => { editor.selection.setRng(pos.toRange()); }); } }; export { needsToHaveNbsp, normalizeNbspMiddle, normalizeNbspsInEditor };