slate-angular 20.0.0 → 20.2.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/slate-angular.mjs +266 -86
- package/fesm2022/slate-angular.mjs.map +1 -1
- package/index.d.ts +46 -22
- package/package.json +1 -1
- package/styles/index.scss +14 -1
|
@@ -2,7 +2,7 @@ import { Editor, Range, Element, Transforms, Text as Text$1, Node, Path } from '
|
|
|
2
2
|
import { EDITOR_TO_ELEMENT, NODE_TO_ELEMENT, DOMEditor, normalizeDOMPoint, isDOMSelection, IS_CHROME as IS_CHROME$1, hasShadowRoot, isDOMElement, NODE_TO_PARENT, NODE_TO_INDEX, IS_FOCUSED, isDOMNode, withDOM, NODE_TO_KEY, ELEMENT_TO_NODE, getDefaultView, EDITOR_TO_WINDOW, IS_READ_ONLY, EDITOR_TO_ON_CHANGE, TRIPLE_CLICK, isPlainTextOnlyPaste } from 'slate-dom';
|
|
3
3
|
import { isKeyHotkey } from 'is-hotkey';
|
|
4
4
|
import * as i0 from '@angular/core';
|
|
5
|
-
import { TemplateRef,
|
|
5
|
+
import { TemplateRef, ComponentRef, IterableDiffers, inject, ViewContainerRef, forwardRef, HostBinding, Input, ChangeDetectionStrategy, Component, NgModule, ElementRef, ChangeDetectorRef, Directive, ViewChild } from '@angular/core';
|
|
6
6
|
import { direction } from 'direction';
|
|
7
7
|
import scrollIntoView from 'scroll-into-view-if-needed';
|
|
8
8
|
import { Subject } from 'rxjs';
|
|
@@ -470,6 +470,8 @@ const HAS_BEFORE_INPUT_SUPPORT = !IS_CHROME_LEGACY &&
|
|
|
470
470
|
globalThis.InputEvent &&
|
|
471
471
|
// @ts-ignore The `getTargetRanges` property isn't recognized.
|
|
472
472
|
typeof globalThis.InputEvent.prototype.getTargetRanges === 'function';
|
|
473
|
+
const VIRTUAL_SCROLL_DEFAULT_BUFFER_COUNT = 3;
|
|
474
|
+
const VIRTUAL_SCROLL_DEFAULT_BLOCK_HEIGHT = 40;
|
|
473
475
|
|
|
474
476
|
/**
|
|
475
477
|
* Hotkey mappings for each platform.
|
|
@@ -839,6 +841,9 @@ const getContentHeight = (element) => {
|
|
|
839
841
|
}
|
|
840
842
|
return Math.max(contentHeight, 0);
|
|
841
843
|
};
|
|
844
|
+
const getZeroTextNode = () => {
|
|
845
|
+
return document.createTextNode('\uFEFF');
|
|
846
|
+
};
|
|
842
847
|
|
|
843
848
|
const buildHTMLText = (wrapper, attach, data) => {
|
|
844
849
|
const stringObj = JSON.stringify(data);
|
|
@@ -1512,38 +1517,12 @@ function restoreDom(editor, execute) {
|
|
|
1512
1517
|
}, 0);
|
|
1513
1518
|
}
|
|
1514
1519
|
|
|
1515
|
-
class
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
}
|
|
1519
|
-
get centerContainerElement() {
|
|
1520
|
-
return this.centerContainer.nativeElement;
|
|
1521
|
-
}
|
|
1522
|
-
constructor(elementRef) {
|
|
1523
|
-
this.elementRef = elementRef;
|
|
1524
|
-
}
|
|
1525
|
-
ngOnInit() {
|
|
1526
|
-
this.nativeElement.classList.add(`slate-block-card`);
|
|
1527
|
-
}
|
|
1528
|
-
append() {
|
|
1529
|
-
this.centerRootNodes.forEach(rootNode => !this.centerContainerElement.contains(rootNode) && this.centerContainerElement.appendChild(rootNode));
|
|
1530
|
-
}
|
|
1531
|
-
initializeCenter(rootNodes) {
|
|
1532
|
-
this.centerRootNodes = rootNodes;
|
|
1533
|
-
this.append();
|
|
1520
|
+
class FlavourRef {
|
|
1521
|
+
destroy() {
|
|
1522
|
+
this.instance.onDestroy();
|
|
1534
1523
|
}
|
|
1535
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: SlateBlockCard, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1536
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.12", type: SlateBlockCard, isStandalone: true, selector: "slate-block-card, [slateBlockCard]", viewQueries: [{ propertyName: "centerContainer", first: true, predicate: ["centerContainer"], descendants: true, static: true }], ngImport: i0, template: "<span card-target=\"card-left\" class=\"card-left\">{{ '\\uFEFF' }}</span>\n<div card-target=\"card-center\" #centerContainer></div>\n<span card-target=\"card-right\" class=\"card-right\">{{ '\\uFEFF' }}</span>\n" }); }
|
|
1537
1524
|
}
|
|
1538
|
-
|
|
1539
|
-
type: Component,
|
|
1540
|
-
args: [{ selector: 'slate-block-card, [slateBlockCard]', standalone: true, template: "<span card-target=\"card-left\" class=\"card-left\">{{ '\\uFEFF' }}</span>\n<div card-target=\"card-center\" #centerContainer></div>\n<span card-target=\"card-right\" class=\"card-right\">{{ '\\uFEFF' }}</span>\n" }]
|
|
1541
|
-
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { centerContainer: [{
|
|
1542
|
-
type: ViewChild,
|
|
1543
|
-
args: ['centerContainer', { static: true }]
|
|
1544
|
-
}] } });
|
|
1545
|
-
|
|
1546
|
-
class FlavourRef {
|
|
1525
|
+
class BlockCardRef {
|
|
1547
1526
|
destroy() {
|
|
1548
1527
|
this.instance.onDestroy();
|
|
1549
1528
|
}
|
|
@@ -1706,6 +1685,7 @@ class BaseFlavour {
|
|
|
1706
1685
|
}
|
|
1707
1686
|
}
|
|
1708
1687
|
|
|
1688
|
+
const DEFAULT_ELEMENT_HEIGHT = 24;
|
|
1709
1689
|
class BaseElementFlavour extends BaseFlavour {
|
|
1710
1690
|
constructor() {
|
|
1711
1691
|
super(...arguments);
|
|
@@ -1800,6 +1780,9 @@ class BaseElementFlavour extends BaseFlavour {
|
|
|
1800
1780
|
readonly: this._context.readonly
|
|
1801
1781
|
};
|
|
1802
1782
|
}
|
|
1783
|
+
getRealHeight() {
|
|
1784
|
+
return Promise.resolve(this.nativeElement.offsetHeight);
|
|
1785
|
+
}
|
|
1803
1786
|
}
|
|
1804
1787
|
|
|
1805
1788
|
class DefaultElementFlavour extends BaseElementFlavour {
|
|
@@ -1995,7 +1978,7 @@ const createEmptyOrVoidStringNode = () => {
|
|
|
1995
1978
|
stringNode.setAttribute('data-slate-string', 'true');
|
|
1996
1979
|
stringNode.setAttribute('data-slate-zero-width', 'z');
|
|
1997
1980
|
stringNode.setAttribute('data-slate-length', '0');
|
|
1998
|
-
const zeroWidthSpace =
|
|
1981
|
+
const zeroWidthSpace = getZeroTextNode();
|
|
1999
1982
|
stringNode.appendChild(zeroWidthSpace);
|
|
2000
1983
|
stringNode.setAttribute('editable-text', '');
|
|
2001
1984
|
return stringNode;
|
|
@@ -2006,7 +1989,7 @@ const createCompatibleStringNode = (text) => {
|
|
|
2006
1989
|
stringNode.textContent = text;
|
|
2007
1990
|
stringNode.setAttribute('editable-text', '');
|
|
2008
1991
|
const zeroWidthSpan = document.createElement('span');
|
|
2009
|
-
const zeroWidthSpace =
|
|
1992
|
+
const zeroWidthSpace = getZeroTextNode();
|
|
2010
1993
|
zeroWidthSpan.setAttribute('data-slate-zero-width', '');
|
|
2011
1994
|
zeroWidthSpan.appendChild(zeroWidthSpace);
|
|
2012
1995
|
stringNode.appendChild(zeroWidthSpan);
|
|
@@ -2016,7 +1999,7 @@ const createLineBreakEmptyStringDOM = (elementStringLength) => {
|
|
|
2016
1999
|
const stringNode = document.createElement('span');
|
|
2017
2000
|
stringNode.setAttribute('data-slate-zero-width', 'n');
|
|
2018
2001
|
stringNode.setAttribute('data-slate-length', `${elementStringLength}`);
|
|
2019
|
-
const zeroWidthSpace =
|
|
2002
|
+
const zeroWidthSpace = getZeroTextNode();
|
|
2020
2003
|
stringNode.appendChild(zeroWidthSpace);
|
|
2021
2004
|
const brNode = document.createElement('br');
|
|
2022
2005
|
stringNode.appendChild(brNode);
|
|
@@ -2226,6 +2209,49 @@ const createText = (text) => {
|
|
|
2226
2209
|
return { nativeElement };
|
|
2227
2210
|
};
|
|
2228
2211
|
|
|
2212
|
+
const SLATE_BLOCK_CARD_CLASS_NAME = 'slate-block-card';
|
|
2213
|
+
class SlateBlockCard {
|
|
2214
|
+
onInit() {
|
|
2215
|
+
const nativeElement = document.createElement('div');
|
|
2216
|
+
nativeElement.classList.add(SLATE_BLOCK_CARD_CLASS_NAME);
|
|
2217
|
+
this.nativeElement = nativeElement;
|
|
2218
|
+
this.createContent();
|
|
2219
|
+
}
|
|
2220
|
+
createContent() {
|
|
2221
|
+
const leftCaret = document.createElement('span');
|
|
2222
|
+
leftCaret.setAttribute(`card-target`, 'card-left');
|
|
2223
|
+
leftCaret.classList.add('card-left');
|
|
2224
|
+
leftCaret.appendChild(getZeroTextNode());
|
|
2225
|
+
const rightCaret = document.createElement('span');
|
|
2226
|
+
rightCaret.setAttribute(`card-target`, 'card-right');
|
|
2227
|
+
rightCaret.classList.add('card-right');
|
|
2228
|
+
rightCaret.appendChild(getZeroTextNode());
|
|
2229
|
+
const center = document.createElement('div');
|
|
2230
|
+
center.setAttribute(`card-target`, 'card-center');
|
|
2231
|
+
this.nativeElement.appendChild(leftCaret);
|
|
2232
|
+
this.nativeElement.appendChild(center);
|
|
2233
|
+
this.nativeElement.appendChild(rightCaret);
|
|
2234
|
+
this.centerContainer = center;
|
|
2235
|
+
}
|
|
2236
|
+
append() {
|
|
2237
|
+
this.centerRootNodes.forEach(rootNode => !this.centerContainer.contains(rootNode) && this.centerContainer.appendChild(rootNode));
|
|
2238
|
+
}
|
|
2239
|
+
initializeCenter(rootNodes) {
|
|
2240
|
+
this.centerRootNodes = rootNodes;
|
|
2241
|
+
this.append();
|
|
2242
|
+
}
|
|
2243
|
+
onDestroy() {
|
|
2244
|
+
this.nativeElement.remove();
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
const getBlockCardByNativeElement = (nativeElement) => {
|
|
2248
|
+
const blockCardElement = nativeElement?.parentElement?.parentElement;
|
|
2249
|
+
if (blockCardElement && blockCardElement.classList.contains(SLATE_BLOCK_CARD_CLASS_NAME)) {
|
|
2250
|
+
return blockCardElement;
|
|
2251
|
+
}
|
|
2252
|
+
return null;
|
|
2253
|
+
};
|
|
2254
|
+
|
|
2229
2255
|
class ListRender {
|
|
2230
2256
|
constructor(viewContext, viewContainerRef, getOutletParent, getOutletElement) {
|
|
2231
2257
|
this.viewContext = viewContext;
|
|
@@ -2242,14 +2268,16 @@ class ListRender {
|
|
|
2242
2268
|
initialize(children, parent, childrenContext) {
|
|
2243
2269
|
this.initialized = true;
|
|
2244
2270
|
this.children = children;
|
|
2271
|
+
const isRoot = parent === this.viewContext.editor;
|
|
2272
|
+
const firstIndex = isRoot ? this.viewContext.editor.children.indexOf(children[0]) : 0;
|
|
2245
2273
|
const parentPath = AngularEditor.findPath(this.viewContext.editor, parent);
|
|
2246
|
-
children.forEach((descendant,
|
|
2247
|
-
NODE_TO_INDEX.set(descendant,
|
|
2274
|
+
children.forEach((descendant, _index) => {
|
|
2275
|
+
NODE_TO_INDEX.set(descendant, firstIndex + _index);
|
|
2248
2276
|
NODE_TO_PARENT.set(descendant, parent);
|
|
2249
|
-
const context = getContext(
|
|
2277
|
+
const context = getContext(firstIndex + _index, descendant, parentPath, childrenContext, this.viewContext);
|
|
2250
2278
|
const viewType = getViewType(descendant, parent, this.viewContext);
|
|
2251
2279
|
const view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2252
|
-
const blockCard = createBlockCard(descendant, view, this.
|
|
2280
|
+
const blockCard = createBlockCard(descendant, view, this.viewContext);
|
|
2253
2281
|
this.views.push(view);
|
|
2254
2282
|
this.contexts.push(context);
|
|
2255
2283
|
this.viewTypes.push(viewType);
|
|
@@ -2274,6 +2302,8 @@ class ListRender {
|
|
|
2274
2302
|
const outletParent = this.getOutletParent();
|
|
2275
2303
|
const diffResult = this.differ.diff(children);
|
|
2276
2304
|
const parentPath = AngularEditor.findPath(this.viewContext.editor, parent);
|
|
2305
|
+
const isRoot = parent === this.viewContext.editor;
|
|
2306
|
+
const firstIndex = isRoot ? this.viewContext.editor.children.indexOf(children[0]) : 0;
|
|
2277
2307
|
if (diffResult) {
|
|
2278
2308
|
let firstRootNode = getRootNodes(this.views[0], this.blockCards[0])[0];
|
|
2279
2309
|
const newContexts = [];
|
|
@@ -2281,16 +2311,17 @@ class ListRender {
|
|
|
2281
2311
|
const newViews = [];
|
|
2282
2312
|
const newBlockCards = [];
|
|
2283
2313
|
diffResult.forEachItem(record => {
|
|
2284
|
-
|
|
2314
|
+
const currentIndex = firstIndex + record.currentIndex;
|
|
2315
|
+
NODE_TO_INDEX.set(record.item, currentIndex);
|
|
2285
2316
|
NODE_TO_PARENT.set(record.item, parent);
|
|
2286
|
-
let context = getContext(
|
|
2317
|
+
let context = getContext(currentIndex, record.item, parentPath, childrenContext, this.viewContext);
|
|
2287
2318
|
const viewType = getViewType(record.item, parent, this.viewContext);
|
|
2288
2319
|
newViewTypes.push(viewType);
|
|
2289
2320
|
let view;
|
|
2290
2321
|
let blockCard;
|
|
2291
2322
|
if (record.previousIndex === null) {
|
|
2292
2323
|
view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2293
|
-
blockCard = createBlockCard(record.item, view, this.
|
|
2324
|
+
blockCard = createBlockCard(record.item, view, this.viewContext);
|
|
2294
2325
|
newContexts.push(context);
|
|
2295
2326
|
newViews.push(view);
|
|
2296
2327
|
newBlockCards.push(blockCard);
|
|
@@ -2303,7 +2334,7 @@ class ListRender {
|
|
|
2303
2334
|
const previousBlockCard = this.blockCards[record.previousIndex];
|
|
2304
2335
|
if (previousViewType !== viewType) {
|
|
2305
2336
|
view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2306
|
-
blockCard = createBlockCard(record.item, view, this.
|
|
2337
|
+
blockCard = createBlockCard(record.item, view, this.viewContext);
|
|
2307
2338
|
const firstRootNode = getRootNodes(previousView, previousBlockCard)[0];
|
|
2308
2339
|
const newRootNodes = getRootNodes(view, blockCard);
|
|
2309
2340
|
firstRootNode.replaceWith(...newRootNodes);
|
|
@@ -2351,16 +2382,16 @@ class ListRender {
|
|
|
2351
2382
|
}
|
|
2352
2383
|
else {
|
|
2353
2384
|
const newContexts = [];
|
|
2354
|
-
this.children.forEach((child,
|
|
2355
|
-
NODE_TO_INDEX.set(child,
|
|
2385
|
+
this.children.forEach((child, _index) => {
|
|
2386
|
+
NODE_TO_INDEX.set(child, firstIndex + _index);
|
|
2356
2387
|
NODE_TO_PARENT.set(child, parent);
|
|
2357
|
-
let context = getContext(
|
|
2358
|
-
const previousContext = this.contexts[
|
|
2388
|
+
let context = getContext(firstIndex + _index, child, parentPath, childrenContext, this.viewContext);
|
|
2389
|
+
const previousContext = this.contexts[_index];
|
|
2359
2390
|
if (memoizedContext(this.viewContext, child, previousContext, context)) {
|
|
2360
2391
|
context = previousContext;
|
|
2361
2392
|
}
|
|
2362
2393
|
else {
|
|
2363
|
-
updateContext(this.views[
|
|
2394
|
+
updateContext(this.views[_index], context, this.viewContext);
|
|
2364
2395
|
}
|
|
2365
2396
|
newContexts.push(context);
|
|
2366
2397
|
});
|
|
@@ -2461,16 +2492,15 @@ function getViewType(item, parent, viewContext) {
|
|
|
2461
2492
|
return isVoid ? VoidTextFlavour : (viewContext.renderText && viewContext.renderText(item)) || DefaultTextFlavour;
|
|
2462
2493
|
}
|
|
2463
2494
|
}
|
|
2464
|
-
function createBlockCard(item, view,
|
|
2495
|
+
function createBlockCard(item, view, viewContext) {
|
|
2465
2496
|
const isBlockCard = viewContext.editor.isBlockCard(item);
|
|
2466
2497
|
if (isBlockCard) {
|
|
2467
2498
|
const rootNodes = getRootNodes(view);
|
|
2468
|
-
const
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
return blockCardComponentRef;
|
|
2499
|
+
const blockCardRef = new BlockCardRef();
|
|
2500
|
+
blockCardRef.instance = new SlateBlockCard();
|
|
2501
|
+
blockCardRef.instance.onInit();
|
|
2502
|
+
blockCardRef.instance.initializeCenter(rootNodes);
|
|
2503
|
+
return blockCardRef;
|
|
2474
2504
|
}
|
|
2475
2505
|
else {
|
|
2476
2506
|
return null;
|
|
@@ -2522,6 +2552,17 @@ function executeAfterViewInit(editor) {
|
|
|
2522
2552
|
// not correctly clipboardData on beforeinput
|
|
2523
2553
|
const forceOnDOMPaste = IS_SAFARI;
|
|
2524
2554
|
class SlateEditable {
|
|
2555
|
+
set virtualScroll(config) {
|
|
2556
|
+
this.virtualConfig = config;
|
|
2557
|
+
this.refreshVirtualViewAnimId && cancelAnimationFrame(this.refreshVirtualViewAnimId);
|
|
2558
|
+
this.refreshVirtualViewAnimId = requestAnimationFrame(() => {
|
|
2559
|
+
this.refreshVirtualView();
|
|
2560
|
+
if (this.listRender.initialized) {
|
|
2561
|
+
this.listRender.update(this.renderedChildren, this.editor, this.context);
|
|
2562
|
+
}
|
|
2563
|
+
this.scheduleMeasureVisibleHeights();
|
|
2564
|
+
});
|
|
2565
|
+
}
|
|
2525
2566
|
get hasBeforeInputSupport() {
|
|
2526
2567
|
return HAS_BEFORE_INPUT_SUPPORT;
|
|
2527
2568
|
}
|
|
@@ -2544,6 +2585,8 @@ class SlateEditable {
|
|
|
2544
2585
|
this.isStrictDecorate = true;
|
|
2545
2586
|
this.trackBy = () => null;
|
|
2546
2587
|
this.readonly = false;
|
|
2588
|
+
this.virtualTopPadding = 0;
|
|
2589
|
+
this.virtualBottomPadding = 0;
|
|
2547
2590
|
//#endregion
|
|
2548
2591
|
//#region DOM attr
|
|
2549
2592
|
this.spellCheck = false;
|
|
@@ -2557,6 +2600,15 @@ class SlateEditable {
|
|
|
2557
2600
|
this.getOutletParent = () => {
|
|
2558
2601
|
return this.elementRef.nativeElement;
|
|
2559
2602
|
};
|
|
2603
|
+
this.virtualConfig = {
|
|
2604
|
+
enabled: false,
|
|
2605
|
+
scrollTop: 0,
|
|
2606
|
+
viewportHeight: 0
|
|
2607
|
+
};
|
|
2608
|
+
this.renderedChildren = [];
|
|
2609
|
+
this.virtualVisibleIndexes = new Set();
|
|
2610
|
+
this.measuredHeights = new Map();
|
|
2611
|
+
this.measurePending = false;
|
|
2560
2612
|
}
|
|
2561
2613
|
ngOnInit() {
|
|
2562
2614
|
this.editor.injector = this.injector;
|
|
@@ -2611,12 +2663,15 @@ class SlateEditable {
|
|
|
2611
2663
|
if (value && value.length) {
|
|
2612
2664
|
this.editor.children = value;
|
|
2613
2665
|
this.initializeContext();
|
|
2666
|
+
this.refreshVirtualView();
|
|
2667
|
+
const childrenForRender = this.renderedChildren;
|
|
2614
2668
|
if (!this.listRender.initialized) {
|
|
2615
|
-
this.listRender.initialize(
|
|
2669
|
+
this.listRender.initialize(childrenForRender, this.editor, this.context);
|
|
2616
2670
|
}
|
|
2617
2671
|
else {
|
|
2618
|
-
this.listRender.update(
|
|
2672
|
+
this.listRender.update(childrenForRender, this.editor, this.context);
|
|
2619
2673
|
}
|
|
2674
|
+
this.scheduleMeasureVisibleHeights();
|
|
2620
2675
|
this.cdr.markForCheck();
|
|
2621
2676
|
}
|
|
2622
2677
|
}
|
|
@@ -2737,7 +2792,9 @@ class SlateEditable {
|
|
|
2737
2792
|
ngDoCheck() { }
|
|
2738
2793
|
forceRender() {
|
|
2739
2794
|
this.updateContext();
|
|
2740
|
-
this.
|
|
2795
|
+
this.refreshVirtualView();
|
|
2796
|
+
this.listRender.update(this.renderedChildren, this.editor, this.context);
|
|
2797
|
+
this.scheduleMeasureVisibleHeights();
|
|
2741
2798
|
// repair collaborative editing when Chinese input is interrupted by other users' cursors
|
|
2742
2799
|
// when the DOMElement where the selection is located is removed
|
|
2743
2800
|
// the compositionupdate and compositionend events will no longer be fired
|
|
@@ -2776,7 +2833,9 @@ class SlateEditable {
|
|
|
2776
2833
|
render() {
|
|
2777
2834
|
const changed = this.updateContext();
|
|
2778
2835
|
if (changed) {
|
|
2779
|
-
this.
|
|
2836
|
+
this.refreshVirtualView();
|
|
2837
|
+
this.listRender.update(this.renderedChildren, this.editor, this.context);
|
|
2838
|
+
this.scheduleMeasureVisibleHeights();
|
|
2780
2839
|
}
|
|
2781
2840
|
}
|
|
2782
2841
|
updateContext() {
|
|
@@ -2839,6 +2898,128 @@ class SlateEditable {
|
|
|
2839
2898
|
decorations.push(...placeholderDecorations);
|
|
2840
2899
|
return decorations;
|
|
2841
2900
|
}
|
|
2901
|
+
shouldUseVirtual() {
|
|
2902
|
+
return !!(this.virtualConfig && this.virtualConfig.enabled);
|
|
2903
|
+
}
|
|
2904
|
+
refreshVirtualView() {
|
|
2905
|
+
const children = (this.editor.children || []);
|
|
2906
|
+
if (!children.length || !this.shouldUseVirtual()) {
|
|
2907
|
+
this.renderedChildren = children;
|
|
2908
|
+
this.virtualTopPadding = 0;
|
|
2909
|
+
this.virtualBottomPadding = 0;
|
|
2910
|
+
this.virtualVisibleIndexes.clear();
|
|
2911
|
+
return;
|
|
2912
|
+
}
|
|
2913
|
+
const scrollTop = this.virtualConfig.scrollTop ?? 0;
|
|
2914
|
+
const viewportHeight = this.virtualConfig.viewportHeight ?? 0;
|
|
2915
|
+
if (!viewportHeight) {
|
|
2916
|
+
// 已经启用虚拟滚动,但可视区域高度还未获取到,先置空不渲染
|
|
2917
|
+
this.renderedChildren = [];
|
|
2918
|
+
this.virtualTopPadding = 0;
|
|
2919
|
+
this.virtualBottomPadding = 0;
|
|
2920
|
+
this.virtualVisibleIndexes.clear();
|
|
2921
|
+
return;
|
|
2922
|
+
}
|
|
2923
|
+
const bufferCount = this.virtualConfig.bufferCount ?? VIRTUAL_SCROLL_DEFAULT_BUFFER_COUNT;
|
|
2924
|
+
const heights = children.map((_, idx) => this.getBlockHeight(idx));
|
|
2925
|
+
const accumulatedHeights = this.buildAccumulatedHeight(heights);
|
|
2926
|
+
const total = accumulatedHeights[accumulatedHeights.length - 1] || 0;
|
|
2927
|
+
let visibleStart = 0;
|
|
2928
|
+
// 按真实或估算高度往后累加,找到滚动起点所在块
|
|
2929
|
+
while (visibleStart < heights.length && accumulatedHeights[visibleStart + 1] <= scrollTop) {
|
|
2930
|
+
visibleStart++;
|
|
2931
|
+
}
|
|
2932
|
+
// 向上预留 bufferCount 块
|
|
2933
|
+
const startIndex = Math.max(0, visibleStart - bufferCount);
|
|
2934
|
+
const top = accumulatedHeights[startIndex];
|
|
2935
|
+
const bufferBelowHeight = this.getBufferBelowHeight(viewportHeight, visibleStart, bufferCount);
|
|
2936
|
+
const targetHeight = accumulatedHeights[visibleStart] - top + viewportHeight + bufferBelowHeight;
|
|
2937
|
+
const visible = [];
|
|
2938
|
+
const visibleIndexes = [];
|
|
2939
|
+
let accumulated = 0;
|
|
2940
|
+
let cursor = startIndex;
|
|
2941
|
+
// 循环累计高度超出目标高度(可视高度 + 上下 buffer)
|
|
2942
|
+
while (cursor < children.length && accumulated < targetHeight) {
|
|
2943
|
+
visible.push(children[cursor]);
|
|
2944
|
+
visibleIndexes.push(cursor);
|
|
2945
|
+
accumulated += this.getBlockHeight(cursor);
|
|
2946
|
+
cursor++;
|
|
2947
|
+
}
|
|
2948
|
+
const bottom = Math.max(total - top - accumulated, 0); // 下占位高度
|
|
2949
|
+
this.renderedChildren = visible.length ? visible : children;
|
|
2950
|
+
// padding 占位
|
|
2951
|
+
this.virtualTopPadding = this.renderedChildren === visible ? Math.round(top) : 0;
|
|
2952
|
+
this.virtualBottomPadding = this.renderedChildren === visible ? Math.round(bottom) : 0;
|
|
2953
|
+
this.virtualVisibleIndexes = new Set(visibleIndexes);
|
|
2954
|
+
}
|
|
2955
|
+
getBlockHeight(index) {
|
|
2956
|
+
const node = this.editor.children[index];
|
|
2957
|
+
if (!node) {
|
|
2958
|
+
return VIRTUAL_SCROLL_DEFAULT_BLOCK_HEIGHT;
|
|
2959
|
+
}
|
|
2960
|
+
const key = AngularEditor.findKey(this.editor, node);
|
|
2961
|
+
return this.measuredHeights.get(key.id) ?? VIRTUAL_SCROLL_DEFAULT_BLOCK_HEIGHT;
|
|
2962
|
+
}
|
|
2963
|
+
buildAccumulatedHeight(heights) {
|
|
2964
|
+
const accumulatedHeights = new Array(heights.length + 1).fill(0);
|
|
2965
|
+
for (let i = 0; i < heights.length; i++) {
|
|
2966
|
+
// 存储前 i 个的累计高度
|
|
2967
|
+
accumulatedHeights[i + 1] = accumulatedHeights[i] + heights[i];
|
|
2968
|
+
}
|
|
2969
|
+
return accumulatedHeights;
|
|
2970
|
+
}
|
|
2971
|
+
getBufferBelowHeight(viewportHeight, visibleStart, bufferCount) {
|
|
2972
|
+
let blockHeight = 0;
|
|
2973
|
+
let start = visibleStart;
|
|
2974
|
+
// 循环累计高度超出视图高度代表找到向下缓冲区的起始位置
|
|
2975
|
+
while (blockHeight < viewportHeight) {
|
|
2976
|
+
blockHeight += this.getBlockHeight(start);
|
|
2977
|
+
start++;
|
|
2978
|
+
}
|
|
2979
|
+
let bufferHeight = 0;
|
|
2980
|
+
for (let i = start; i < start + bufferCount; i++) {
|
|
2981
|
+
bufferHeight += this.getBlockHeight(i);
|
|
2982
|
+
}
|
|
2983
|
+
return bufferHeight;
|
|
2984
|
+
}
|
|
2985
|
+
scheduleMeasureVisibleHeights() {
|
|
2986
|
+
if (!this.shouldUseVirtual()) {
|
|
2987
|
+
return;
|
|
2988
|
+
}
|
|
2989
|
+
if (this.measurePending) {
|
|
2990
|
+
return;
|
|
2991
|
+
}
|
|
2992
|
+
this.measurePending = true;
|
|
2993
|
+
this.measureVisibleHeightsAnimId && cancelAnimationFrame(this.measureVisibleHeightsAnimId);
|
|
2994
|
+
this.measureVisibleHeightsAnimId = requestAnimationFrame(() => {
|
|
2995
|
+
this.measureVisibleHeights();
|
|
2996
|
+
this.measurePending = false;
|
|
2997
|
+
});
|
|
2998
|
+
}
|
|
2999
|
+
measureVisibleHeights() {
|
|
3000
|
+
const children = (this.editor.children || []);
|
|
3001
|
+
this.virtualVisibleIndexes.forEach(index => {
|
|
3002
|
+
const node = children[index];
|
|
3003
|
+
if (!node) {
|
|
3004
|
+
return;
|
|
3005
|
+
}
|
|
3006
|
+
const key = AngularEditor.findKey(this.editor, node);
|
|
3007
|
+
// 跳过已测过的块
|
|
3008
|
+
if (this.measuredHeights.has(key.id)) {
|
|
3009
|
+
return;
|
|
3010
|
+
}
|
|
3011
|
+
const view = ELEMENT_TO_COMPONENT.get(node);
|
|
3012
|
+
if (!view) {
|
|
3013
|
+
return;
|
|
3014
|
+
}
|
|
3015
|
+
view.getRealHeight()?.then(height => {
|
|
3016
|
+
const actualHeight = height +
|
|
3017
|
+
parseFloat(getComputedStyle(view.nativeElement).marginTop) +
|
|
3018
|
+
parseFloat(getComputedStyle(view.nativeElement).marginBottom);
|
|
3019
|
+
this.measuredHeights.set(key.id, actualHeight);
|
|
3020
|
+
});
|
|
3021
|
+
});
|
|
3022
|
+
}
|
|
2842
3023
|
//#region event proxy
|
|
2843
3024
|
addEventListener(eventName, listener, target = this.elementRef.nativeElement) {
|
|
2844
3025
|
this.manualListeners.push(this.renderer2.listen(target, eventName, (event) => {
|
|
@@ -3538,30 +3719,37 @@ class SlateEditable {
|
|
|
3538
3719
|
EDITOR_TO_ON_CHANGE.delete(this.editor);
|
|
3539
3720
|
}
|
|
3540
3721
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: SlateEditable, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3541
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.12", type: SlateEditable, isStandalone: true, selector: "slate-editable", inputs: { editor: "editor", renderElement: "renderElement", renderLeaf: "renderLeaf", renderText: "renderText", decorate: "decorate", placeholderDecorate: "placeholderDecorate", scrollSelectionIntoView: "scrollSelectionIntoView", isStrictDecorate: "isStrictDecorate", trackBy: "trackBy", readonly: "readonly", placeholder: "placeholder", beforeInput: "beforeInput", blur: "blur", click: "click", compositionEnd: "compositionEnd", compositionUpdate: "compositionUpdate", compositionStart: "compositionStart", copy: "copy", cut: "cut", dragOver: "dragOver", dragStart: "dragStart", dragEnd: "dragEnd", drop: "drop", focus: "focus", keydown: "keydown", paste: "paste", spellCheck: "spellCheck", autoCorrect: "autoCorrect", autoCapitalize: "autoCapitalize" }, host: { properties: { "attr.contenteditable": "readonly ? undefined : true", "attr.role": "readonly ? undefined : 'textbox'", "attr.spellCheck": "!hasBeforeInputSupport ? false : spellCheck", "attr.autoCorrect": "!hasBeforeInputSupport ? 'false' : autoCorrect", "attr.autoCapitalize": "!hasBeforeInputSupport ? 'false' : autoCapitalize", "attr.data-slate-editor": "this.dataSlateEditor", "attr.data-slate-node": "this.dataSlateNode", "attr.data-gramm": "this.dataGramm" }, classAttribute: "slate-editable-container" }, providers: [
|
|
3722
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.12", type: SlateEditable, isStandalone: true, selector: "slate-editable", inputs: { editor: "editor", renderElement: "renderElement", renderLeaf: "renderLeaf", renderText: "renderText", decorate: "decorate", placeholderDecorate: "placeholderDecorate", scrollSelectionIntoView: "scrollSelectionIntoView", isStrictDecorate: "isStrictDecorate", trackBy: "trackBy", readonly: "readonly", placeholder: "placeholder", virtualScroll: "virtualScroll", beforeInput: "beforeInput", blur: "blur", click: "click", compositionEnd: "compositionEnd", compositionUpdate: "compositionUpdate", compositionStart: "compositionStart", copy: "copy", cut: "cut", dragOver: "dragOver", dragStart: "dragStart", dragEnd: "dragEnd", drop: "drop", focus: "focus", keydown: "keydown", paste: "paste", spellCheck: "spellCheck", autoCorrect: "autoCorrect", autoCapitalize: "autoCapitalize" }, host: { properties: { "attr.contenteditable": "readonly ? undefined : true", "attr.role": "readonly ? undefined : 'textbox'", "attr.spellCheck": "!hasBeforeInputSupport ? false : spellCheck", "attr.autoCorrect": "!hasBeforeInputSupport ? 'false' : autoCorrect", "attr.autoCapitalize": "!hasBeforeInputSupport ? 'false' : autoCapitalize", "style.--virtual-top-padding.px": "this.virtualTopPadding", "style.--virtual-bottom-padding.px": "this.virtualBottomPadding", "attr.data-slate-editor": "this.dataSlateEditor", "attr.data-slate-node": "this.dataSlateNode", "attr.data-gramm": "this.dataGramm" }, classAttribute: "slate-editable-container" }, providers: [
|
|
3542
3723
|
{
|
|
3543
3724
|
provide: NG_VALUE_ACCESSOR,
|
|
3544
3725
|
useExisting: forwardRef(() => SlateEditable),
|
|
3545
3726
|
multi: true
|
|
3546
3727
|
}
|
|
3547
|
-
], usesOnChanges: true, ngImport: i0, template:
|
|
3728
|
+
], usesOnChanges: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3548
3729
|
}
|
|
3549
3730
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: SlateEditable, decorators: [{
|
|
3550
3731
|
type: Component,
|
|
3551
|
-
args: [{
|
|
3732
|
+
args: [{
|
|
3733
|
+
selector: 'slate-editable',
|
|
3734
|
+
host: {
|
|
3552
3735
|
class: 'slate-editable-container',
|
|
3553
3736
|
'[attr.contenteditable]': 'readonly ? undefined : true',
|
|
3554
3737
|
'[attr.role]': `readonly ? undefined : 'textbox'`,
|
|
3555
3738
|
'[attr.spellCheck]': `!hasBeforeInputSupport ? false : spellCheck`,
|
|
3556
3739
|
'[attr.autoCorrect]': `!hasBeforeInputSupport ? 'false' : autoCorrect`,
|
|
3557
3740
|
'[attr.autoCapitalize]': `!hasBeforeInputSupport ? 'false' : autoCapitalize`
|
|
3558
|
-
},
|
|
3741
|
+
},
|
|
3742
|
+
template: '',
|
|
3743
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3744
|
+
providers: [
|
|
3559
3745
|
{
|
|
3560
3746
|
provide: NG_VALUE_ACCESSOR,
|
|
3561
3747
|
useExisting: forwardRef(() => SlateEditable),
|
|
3562
3748
|
multi: true
|
|
3563
3749
|
}
|
|
3564
|
-
],
|
|
3750
|
+
],
|
|
3751
|
+
imports: []
|
|
3752
|
+
}]
|
|
3565
3753
|
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i0.Injector }], propDecorators: { editor: [{
|
|
3566
3754
|
type: Input
|
|
3567
3755
|
}], renderElement: [{
|
|
@@ -3584,6 +3772,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
3584
3772
|
type: Input
|
|
3585
3773
|
}], placeholder: [{
|
|
3586
3774
|
type: Input
|
|
3775
|
+
}], virtualScroll: [{
|
|
3776
|
+
type: Input
|
|
3777
|
+
}], virtualTopPadding: [{
|
|
3778
|
+
type: HostBinding,
|
|
3779
|
+
args: ['style.--virtual-top-padding.px']
|
|
3780
|
+
}], virtualBottomPadding: [{
|
|
3781
|
+
type: HostBinding,
|
|
3782
|
+
args: ['style.--virtual-bottom-padding.px']
|
|
3587
3783
|
}], beforeInput: [{
|
|
3588
3784
|
type: Input
|
|
3589
3785
|
}], blur: [{
|
|
@@ -3709,35 +3905,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
3709
3905
|
}]
|
|
3710
3906
|
}], ctorParameters: () => [{ type: i0.ElementRef }] });
|
|
3711
3907
|
|
|
3712
|
-
class SlateString {
|
|
3713
|
-
ngOnInit() { }
|
|
3714
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: SlateString, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3715
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.12", type: SlateString, isStandalone: true, selector: "span[slateString]", inputs: { context: "context", viewContext: "viewContext" }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3716
|
-
}
|
|
3717
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: SlateString, decorators: [{
|
|
3718
|
-
type: Component,
|
|
3719
|
-
args: [{
|
|
3720
|
-
selector: 'span[slateString]',
|
|
3721
|
-
template: '',
|
|
3722
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3723
|
-
standalone: true
|
|
3724
|
-
}]
|
|
3725
|
-
}], propDecorators: { context: [{
|
|
3726
|
-
type: Input
|
|
3727
|
-
}], viewContext: [{
|
|
3728
|
-
type: Input
|
|
3729
|
-
}] } });
|
|
3730
|
-
|
|
3731
3908
|
class SlateModule {
|
|
3732
3909
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: SlateModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
3733
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.12", ngImport: i0, type: SlateModule, imports: [CommonModule, SlateEditable,
|
|
3910
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.12", ngImport: i0, type: SlateModule, imports: [CommonModule, SlateEditable, SlateChildrenOutlet], exports: [SlateEditable, SlateChildrenOutlet] }); }
|
|
3734
3911
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: SlateModule, imports: [CommonModule] }); }
|
|
3735
3912
|
}
|
|
3736
3913
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: SlateModule, decorators: [{
|
|
3737
3914
|
type: NgModule,
|
|
3738
3915
|
args: [{
|
|
3739
|
-
imports: [CommonModule, SlateEditable,
|
|
3740
|
-
exports: [SlateEditable, SlateChildrenOutlet
|
|
3916
|
+
imports: [CommonModule, SlateEditable, SlateChildrenOutlet],
|
|
3917
|
+
exports: [SlateEditable, SlateChildrenOutlet],
|
|
3741
3918
|
providers: []
|
|
3742
3919
|
}]
|
|
3743
3920
|
}] });
|
|
@@ -3880,6 +4057,9 @@ class BaseElementComponent extends BaseComponent {
|
|
|
3880
4057
|
readonly: this._context.readonly
|
|
3881
4058
|
};
|
|
3882
4059
|
}
|
|
4060
|
+
getRealHeight() {
|
|
4061
|
+
return Promise.resolve(this.nativeElement.offsetHeight);
|
|
4062
|
+
}
|
|
3883
4063
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: BaseElementComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
|
|
3884
4064
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.12", type: BaseElementComponent, isStandalone: true, viewQueries: [{ propertyName: "childrenOutletInstance", first: true, predicate: SlateChildrenOutlet, descendants: true, static: true }], usesInheritance: true, ngImport: i0 }); }
|
|
3885
4065
|
}
|
|
@@ -4034,5 +4214,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
4034
4214
|
* Generated bundle index. Do not edit.
|
|
4035
4215
|
*/
|
|
4036
4216
|
|
|
4037
|
-
export { AngularEditor, BaseComponent, BaseElementComponent, BaseElementFlavour, BaseFlavour, BaseLeafComponent, BaseLeafFlavour, BaseTextComponent, BaseTextFlavour, DefaultTextFlavour, EDITOR_TO_AFTER_VIEW_INIT_QUEUE, ELEMENT_TO_COMPONENT, FAKE_LEFT_BLOCK_CARD_OFFSET, FAKE_RIGHT_BLOCK_CARD_OFFSET, FlavourRef, HAS_BEFORE_INPUT_SUPPORT, IS_ANDROID, IS_APPLE, IS_CHROME, IS_CHROME_LEGACY, IS_EDGE_LEGACY, IS_FIREFOX, IS_FIREFOX_LEGACY, IS_IOS, IS_QQBROWSER, IS_SAFARI, IS_UC_MOBILE, IS_WECHATBROWSER, PLACEHOLDER_SYMBOL, SlateChildrenOutlet, SlateEditable, SlateErrorCode, SlateFragmentAttributeKey, SlateModule,
|
|
4217
|
+
export { AngularEditor, BaseComponent, BaseElementComponent, BaseElementFlavour, BaseFlavour, BaseLeafComponent, BaseLeafFlavour, BaseTextComponent, BaseTextFlavour, BlockCardRef, DEFAULT_ELEMENT_HEIGHT, DefaultTextFlavour, EDITOR_TO_AFTER_VIEW_INIT_QUEUE, ELEMENT_TO_COMPONENT, FAKE_LEFT_BLOCK_CARD_OFFSET, FAKE_RIGHT_BLOCK_CARD_OFFSET, FlavourRef, HAS_BEFORE_INPUT_SUPPORT, IS_ANDROID, IS_APPLE, IS_CHROME, IS_CHROME_LEGACY, IS_EDGE_LEGACY, IS_FIREFOX, IS_FIREFOX_LEGACY, IS_IOS, IS_QQBROWSER, IS_SAFARI, IS_UC_MOBILE, IS_WECHATBROWSER, PLACEHOLDER_SYMBOL, SLATE_BLOCK_CARD_CLASS_NAME, SlateBlockCard, SlateChildrenOutlet, SlateEditable, SlateErrorCode, SlateFragmentAttributeKey, SlateModule, VIRTUAL_SCROLL_DEFAULT_BLOCK_HEIGHT, VIRTUAL_SCROLL_DEFAULT_BUFFER_COUNT, VoidTextFlavour, blobAsString, buildHTMLText, check, completeTable, createClipboardData, createText, createThrottleRAF, defaultScrollSelectionIntoView, fallbackCopyText, getBlockCardByNativeElement, getCardTargetAttribute, getClipboardData, getClipboardFromHTMLText, getContentHeight, getDataTransferClipboard, getDataTransferClipboardText, getNavigatorClipboard, getPlainText, getSelection, getSlateFragmentAttribute, getZeroTextNode, hasAfterContextChange, hasBeforeContextChange, hasBlockCard, hasBlockCardWithNode, hotkeys, isCardCenterByTargetAttr, isCardLeft, isCardLeftByTargetAttr, isCardRightByTargetAttr, isClipboardFile, isClipboardReadSupported, isClipboardWriteSupported, isClipboardWriteTextSupported, isComponentType, isDOMText, isDecoratorRangeListEqual, isFlavourType, isInvalidTable, isTemplateRef, isValid, normalize, setClipboardData, setDataTransferClipboard, setDataTransferClipboardText, setNavigatorClipboard, shallowCompare, stripHtml, withAngular };
|
|
4038
4218
|
//# sourceMappingURL=slate-angular.mjs.map
|