mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Fix lint
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { LookupTree, FlattenedLookupTree, LookupTreeEntry, FlattenedLookupTreeEntry } from './types';
|
||||
import { ILookupTree, IFlattenedLookupTree, ILookupTreeEntry, IFlattenedLookupTreeEntry } from './types';
|
||||
|
||||
export default function flatten(tree: LookupTree): FlattenedLookupTree {
|
||||
const result: FlattenedLookupTree = {};
|
||||
export default function flatten(tree: ILookupTree): IFlattenedLookupTree {
|
||||
const result: IFlattenedLookupTree = {};
|
||||
for (const [glyphId, entry] of Object.entries(tree.individual)) {
|
||||
result[glyphId] = flattenEntry(entry);
|
||||
}
|
||||
@@ -16,8 +16,8 @@ export default function flatten(tree: LookupTree): FlattenedLookupTree {
|
||||
return result;
|
||||
}
|
||||
|
||||
function flattenEntry(entry: LookupTreeEntry): FlattenedLookupTreeEntry {
|
||||
const result: FlattenedLookupTreeEntry = {};
|
||||
function flattenEntry(entry: ILookupTreeEntry): IFlattenedLookupTreeEntry {
|
||||
const result: IFlattenedLookupTreeEntry = {};
|
||||
|
||||
if (entry.forward) {
|
||||
result.forward = flatten(entry.forward);
|
||||
|
||||
@@ -8,31 +8,31 @@ import * as fs from 'fs';
|
||||
import { assert } from 'chai';
|
||||
import { loadBuffer } from './index';
|
||||
|
||||
interface Font {
|
||||
findLigatures(text: string): { outputGlyphs: number[]; contextRanges: [number, number][] };
|
||||
interface IFont {
|
||||
findLigatures(text: string): { outputGlyphs: number[], contextRanges: [number, number][] };
|
||||
findLigatureRanges(text: string): [number, number][];
|
||||
}
|
||||
|
||||
interface TestCase {
|
||||
interface ITestCase {
|
||||
font: string;
|
||||
input: string;
|
||||
glyphs: number[];
|
||||
ranges: [number, number][];
|
||||
}
|
||||
|
||||
const fira = (input: string, glyphs: number[], ranges: [number, number][]): TestCase =>
|
||||
const fira = (input: string, glyphs: number[], ranges: [number, number][]): ITestCase =>
|
||||
({ font: 'Fira Code', input, glyphs, ranges });
|
||||
|
||||
const iosevka = (input: string, glyphs: number[], ranges: [number, number][]): TestCase =>
|
||||
const iosevka = (input: string, glyphs: number[], ranges: [number, number][]): ITestCase =>
|
||||
({ font: 'Iosevka', input, glyphs, ranges });
|
||||
|
||||
const monoid = (input: string, glyphs: number[], ranges: [number, number][]): TestCase =>
|
||||
const monoid = (input: string, glyphs: number[], ranges: [number, number][]): ITestCase =>
|
||||
({ font: 'Monoid', input, glyphs, ranges });
|
||||
|
||||
const ubuntu = (input: string, glyphs: number[], ranges: [number, number][]): TestCase =>
|
||||
const ubuntu = (input: string, glyphs: number[], ranges: [number, number][]): ITestCase =>
|
||||
({ font: 'Ubuntu Mono', input, glyphs, ranges });
|
||||
|
||||
const firaCases: TestCase[] = [
|
||||
const firaCases: ITestCase[] = [
|
||||
fira('abc', [133, 145, 146], []),
|
||||
fira('.=', [1614, 1081], [[0, 2]]),
|
||||
fira('..=', [1614, 1614, 1083], [[0, 3]]),
|
||||
@@ -168,7 +168,7 @@ const firaCases: TestCase[] = [
|
||||
fira('===>', [1614, 1614, 1486, 1148], [[0, 4]])
|
||||
];
|
||||
|
||||
const iosevkaCases: TestCase[] = [
|
||||
const iosevkaCases: ITestCase[] = [
|
||||
iosevka('<-', [31, 3127], [[0, 2]]),
|
||||
iosevka('<--', [31, 3129, 3139], [[0, 3]]),
|
||||
iosevka('<---', [31, 3129, 3150, 3139], [[0, 4]]),
|
||||
@@ -218,7 +218,7 @@ const iosevkaCases: TestCase[] = [
|
||||
iosevka('!===', [3100, 3085, 3085, 3084], [[0, 4]])
|
||||
];
|
||||
|
||||
const monoidCases: TestCase[] = [
|
||||
const monoidCases: ITestCase[] = [
|
||||
monoid('<!--', [775, 775, 775, 643], [[0, 4]]),
|
||||
monoid('-->', [779, 779, 628], [[0, 3]]),
|
||||
monoid('<--', [776, 776, 627], [[0, 3]]),
|
||||
@@ -256,7 +256,7 @@ const monoidCases: TestCase[] = [
|
||||
monoid('__', [763, 764], [[0, 2]])
|
||||
];
|
||||
|
||||
const ubuntuCases: TestCase[] = [
|
||||
const ubuntuCases: ITestCase[] = [
|
||||
ubuntu('==>', [32, 32, 33], [])
|
||||
];
|
||||
|
||||
@@ -267,9 +267,9 @@ const fontPaths: Record<string, string> = {
|
||||
'Ubuntu Mono': path.join(__dirname, '../../fonts/UbuntuMono-Regular.ttf')
|
||||
};
|
||||
|
||||
const fontCache: Map<string, Font> = new Map();
|
||||
const fontCache: Map<string, IFont> = new Map();
|
||||
|
||||
function loadFont(fontName: string): Font {
|
||||
function loadFont(fontName: string): IFont {
|
||||
let font = fontCache.get(fontName);
|
||||
if (!font) {
|
||||
const fontPath = fontPaths[fontName];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as opentype from 'opentype.js';
|
||||
import LRUCache = require('lru-cache');
|
||||
|
||||
import { Font, LigatureData, FlattenedLookupTree, LookupTree, Options } from './types';
|
||||
import { IFont, ILigatureData, IFlattenedLookupTree, ILookupTree, IOptions } from './types';
|
||||
import mergeTrees from './merge';
|
||||
import walkTree from './walk';
|
||||
import mergeRange from './mergeRange';
|
||||
@@ -12,19 +12,19 @@ import buildTreeGsubType6Format3 from './processors/6-3';
|
||||
import buildTreeGsubType8Format1 from './processors/8-1';
|
||||
import flatten from './flatten';
|
||||
|
||||
class FontImpl implements Font {
|
||||
class FontImpl implements IFont {
|
||||
private _font: opentype.Font;
|
||||
private _lookupTrees: { tree: FlattenedLookupTree; processForward: boolean; }[] = [];
|
||||
private _lookupTrees: { tree: IFlattenedLookupTree, processForward: boolean }[] = [];
|
||||
private _glyphLookups: { [glyphId: string]: number[] } = {};
|
||||
private _cache?: LRUCache<string, LigatureData | [number, number][]>;
|
||||
private _cache?: LRUCache<string, ILigatureData | [number, number][]>;
|
||||
|
||||
constructor(font: opentype.Font, options: Required<Options>) {
|
||||
constructor(font: opentype.Font, options: Required<IOptions>) {
|
||||
this._font = font;
|
||||
|
||||
if (options.cacheSize > 0) {
|
||||
this._cache = new LRUCache({
|
||||
max: options.cacheSize,
|
||||
length: ((val: LigatureData | [number, number][], key: string) => key.length) as any
|
||||
length: ((val: ILigatureData | [number, number][], key: string) => key.length) as any
|
||||
});
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class FontImpl implements Font {
|
||||
const lookupGroups = allLookups.filter((l: unknown, i: number) => lookupIndices.some(idx => idx === i));
|
||||
|
||||
for (const [index, lookup] of lookupGroups.entries()) {
|
||||
const trees: LookupTree[] = [];
|
||||
const trees: ILookupTree[] = [];
|
||||
switch (lookup.lookupType) {
|
||||
case 6:
|
||||
for (const [index, table] of lookup.subtables.entries()) {
|
||||
@@ -77,7 +77,7 @@ class FontImpl implements Font {
|
||||
}
|
||||
}
|
||||
|
||||
findLigatures(text: string): LigatureData {
|
||||
public findLigatures(text: string): ILigatureData {
|
||||
const cached = this._cache && this._cache.get(text);
|
||||
if (cached && !Array.isArray(cached)) {
|
||||
return cached;
|
||||
@@ -100,7 +100,7 @@ class FontImpl implements Font {
|
||||
}
|
||||
|
||||
const result = this._findInternal(glyphIds.slice());
|
||||
const finalResult: LigatureData = {
|
||||
const finalResult: ILigatureData = {
|
||||
inputGlyphs: glyphIds,
|
||||
outputGlyphs: result.sequence,
|
||||
contextRanges: result.ranges
|
||||
@@ -112,7 +112,7 @@ class FontImpl implements Font {
|
||||
return finalResult;
|
||||
}
|
||||
|
||||
findLigatureRanges(text: string): [number, number][] {
|
||||
public findLigatureRanges(text: string): [number, number][] {
|
||||
// Short circuit the process if there are no possible ligatures in the
|
||||
// font
|
||||
if (this._lookupTrees.length === 0) {
|
||||
@@ -137,7 +137,7 @@ class FontImpl implements Font {
|
||||
return result.ranges;
|
||||
}
|
||||
|
||||
private _findInternal(sequence: number[]): { sequence: number[]; ranges: [number, number][]; } {
|
||||
private _findInternal(sequence: number[]): { sequence: number[], ranges: [number, number][] } {
|
||||
const ranges: [number, number][] = [];
|
||||
|
||||
let nextLookup = this._getNextLookup(sequence, 0);
|
||||
@@ -207,8 +207,8 @@ class FontImpl implements Font {
|
||||
* @param sequence Input glyph sequence
|
||||
* @param start The first input to try
|
||||
*/
|
||||
private _getNextLookup(sequence: number[], start: number): { index: number | null; first: number; last: number; } {
|
||||
const result: { index: number | null; first: number; last: number; } = {
|
||||
private _getNextLookup(sequence: number[], start: number): { index: number | null, first: number, last: number } {
|
||||
const result: { index: number | null, first: number, last: number } = {
|
||||
index: null,
|
||||
first: Infinity,
|
||||
last: -1
|
||||
@@ -251,7 +251,7 @@ class FontImpl implements Font {
|
||||
*
|
||||
* @param buffer ArrayBuffer of the font to load
|
||||
*/
|
||||
export function loadBuffer(buffer: ArrayBuffer, options?: Options): Font {
|
||||
export function loadBuffer(buffer: ArrayBuffer, options?: IOptions): IFont {
|
||||
const font = opentype.parse(buffer);
|
||||
return new FontImpl(font, {
|
||||
cacheSize: 0,
|
||||
@@ -259,4 +259,4 @@ export function loadBuffer(buffer: ArrayBuffer, options?: Options): Font {
|
||||
});
|
||||
}
|
||||
|
||||
export { Font, LigatureData, Options };
|
||||
export { IFont as Font, ILigatureData as LigatureData, IOptions as Options };
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { assert } from 'chai';
|
||||
import mergeTrees from './merge';
|
||||
|
||||
interface LookupResult {
|
||||
interface ILookupResult {
|
||||
contextRange: [number, number];
|
||||
index: number;
|
||||
subIndex: number;
|
||||
@@ -14,7 +14,7 @@ interface LookupResult {
|
||||
substitutions: number[];
|
||||
}
|
||||
|
||||
function lookup(substitutionGlyph: number, index?: number, subIndex?: number): LookupResult {
|
||||
function lookup(substitutionGlyph: number, index?: number, subIndex?: number): ILookupResult {
|
||||
return {
|
||||
contextRange: [0, 1],
|
||||
index: index || 0,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { LookupTree, LookupTreeEntry } from './types';
|
||||
import { ILookupTree, ILookupTreeEntry } from './types';
|
||||
|
||||
/**
|
||||
* Merges the provided trees into a single lookup tree. When conflicting lookups
|
||||
@@ -8,8 +8,8 @@ import { LookupTree, LookupTreeEntry } from './types';
|
||||
* @param trees Array of trees to merge. Entries in earlier trees are favored
|
||||
* over those in later trees when there is a choice.
|
||||
*/
|
||||
export default function mergeTrees(trees: LookupTree[]): LookupTree {
|
||||
const result: LookupTree = {
|
||||
export default function mergeTrees(trees: ILookupTree[]): ILookupTree {
|
||||
const result: ILookupTree = {
|
||||
individual: {},
|
||||
range: []
|
||||
};
|
||||
@@ -27,7 +27,7 @@ export default function mergeTrees(trees: LookupTree[]): LookupTree {
|
||||
* @param mainTree The tree where the values should be merged
|
||||
* @param mergeTree The tree to be merged into the mainTree
|
||||
*/
|
||||
function mergeSubtree(mainTree: LookupTree, mergeTree: LookupTree): void {
|
||||
function mergeSubtree(mainTree: ILookupTree, mergeTree: ILookupTree): void {
|
||||
// Need to fix this recursively (and handle lookups)
|
||||
for (const [glyphId, value] of Object.entries(mergeTree.individual)) {
|
||||
// The main tree is guaranteed to have no overlaps between the
|
||||
@@ -91,7 +91,7 @@ function mergeSubtree(mainTree: LookupTree, mergeTree: LookupTree): void {
|
||||
mainTree.range.splice(index, 1);
|
||||
index--;
|
||||
|
||||
const entryToMerge: LookupTreeEntry = cloneEntry(resultEntry);
|
||||
const entryToMerge: ILookupTreeEntry = cloneEntry(resultEntry);
|
||||
if (Array.isArray(overlap.both)) {
|
||||
mainTree.range.push({
|
||||
range: overlap.both,
|
||||
@@ -192,7 +192,7 @@ function mergeSubtree(mainTree: LookupTree, mergeTree: LookupTree): void {
|
||||
* @param mainTree The entry where the values should be merged
|
||||
* @param mergeTree The entry to merge into the mainTree
|
||||
*/
|
||||
function mergeTreeEntry(mainTree: LookupTreeEntry, mergeTree: LookupTreeEntry): void {
|
||||
function mergeTreeEntry(mainTree: ILookupTreeEntry, mergeTree: ILookupTreeEntry): void {
|
||||
if (
|
||||
mergeTree.lookup && (
|
||||
!mainTree.lookup ||
|
||||
@@ -220,7 +220,7 @@ function mergeTreeEntry(mainTree: LookupTreeEntry, mergeTree: LookupTreeEntry):
|
||||
}
|
||||
}
|
||||
|
||||
interface Overlap {
|
||||
interface IOverlap {
|
||||
first: (number | [number, number])[];
|
||||
second: (number | [number, number])[];
|
||||
both: number | [number, number] | null;
|
||||
@@ -233,8 +233,8 @@ interface Overlap {
|
||||
* @param first First range
|
||||
* @param second Second range
|
||||
*/
|
||||
function getRangeOverlap(first: [number, number], second: [number, number]): Overlap {
|
||||
const result: Overlap = {
|
||||
function getRangeOverlap(first: [number, number], second: [number, number]): IOverlap {
|
||||
const result: IOverlap = {
|
||||
first: [],
|
||||
second: [],
|
||||
both: null
|
||||
@@ -280,7 +280,7 @@ function getRangeOverlap(first: [number, number], second: [number, number]): Ove
|
||||
* @param first Individual glyph
|
||||
* @param second Range
|
||||
*/
|
||||
function getIndividualOverlap(first: number, second: [number, number]): Overlap {
|
||||
function getIndividualOverlap(first: number, second: [number, number]): IOverlap {
|
||||
// Disjoint
|
||||
if (first < second[0] || first > second[1]) {
|
||||
return {
|
||||
@@ -290,7 +290,7 @@ function getIndividualOverlap(first: number, second: [number, number]): Overlap
|
||||
};
|
||||
}
|
||||
|
||||
const result: Overlap = {
|
||||
const result: IOverlap = {
|
||||
first: [],
|
||||
second: [],
|
||||
both: first
|
||||
@@ -317,9 +317,9 @@ function getIndividualOverlap(first: number, second: [number, number]): Overlap
|
||||
function rangeOrIndividual(start: number, end: number): number | [number, number] {
|
||||
if (end - start === 1) {
|
||||
return start;
|
||||
} else {
|
||||
return [start, end];
|
||||
}
|
||||
return [start, end];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,8 +327,8 @@ function rangeOrIndividual(start: number, end: number): number | [number, number
|
||||
*
|
||||
* @param entry Lookup tree entry to clone
|
||||
*/
|
||||
function cloneEntry(entry: LookupTreeEntry): LookupTreeEntry {
|
||||
const result: LookupTreeEntry = {};
|
||||
function cloneEntry(entry: ILookupTreeEntry): ILookupTreeEntry {
|
||||
const result: ILookupTreeEntry = {};
|
||||
|
||||
if (entry.forward) {
|
||||
result.forward = cloneTree(entry.forward);
|
||||
@@ -356,8 +356,8 @@ function cloneEntry(entry: LookupTreeEntry): LookupTreeEntry {
|
||||
*
|
||||
* @param tree Lookup tree to clone
|
||||
*/
|
||||
function cloneTree(tree: LookupTree): LookupTree {
|
||||
const individual: { [glyphId: string]: LookupTreeEntry; } = {};
|
||||
function cloneTree(tree: ILookupTree): ILookupTree {
|
||||
const individual: { [glyphId: string]: ILookupTreeEntry } = {};
|
||||
for (const [glyphId, entry] of Object.entries(tree.individual)) {
|
||||
individual[glyphId] = cloneEntry(entry);
|
||||
}
|
||||
|
||||
@@ -16,12 +16,14 @@ export default function mergeRange(ranges: [number, number][], newRangeStart: nu
|
||||
// Case 1: New range is before the search range
|
||||
ranges.splice(i, 0, [newRangeStart, newRangeEnd]);
|
||||
return ranges;
|
||||
} else if (newRangeEnd <= range[1]) {
|
||||
}
|
||||
if (newRangeEnd <= range[1]) {
|
||||
// Case 2: New range is either wholly contained within the
|
||||
// search range or overlaps with the front of it
|
||||
range[0] = Math.min(newRangeStart, range[0]);
|
||||
return ranges;
|
||||
} else if (newRangeStart < range[1]) {
|
||||
}
|
||||
if (newRangeStart < range[1]) {
|
||||
// Case 3: New range either wholly contains the search range
|
||||
// or overlaps with the end of it
|
||||
range[0] = Math.min(newRangeStart, range[0]);
|
||||
@@ -36,19 +38,19 @@ export default function mergeRange(ranges: [number, number][], newRangeStart: nu
|
||||
// reach the current one
|
||||
ranges[i - 1][1] = newRangeEnd;
|
||||
return ranges;
|
||||
} else if (newRangeEnd <= range[1]) {
|
||||
}
|
||||
if (newRangeEnd <= range[1]) {
|
||||
// Case 6: New range extends from prvious range into the
|
||||
// current range
|
||||
ranges[i - 1][1] = Math.max(newRangeEnd, range[1]);
|
||||
ranges.splice(i, 1);
|
||||
inRange = false;
|
||||
return ranges;
|
||||
} else {
|
||||
// Case 7: New range extends from previous range past the
|
||||
// end of the current range
|
||||
ranges.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
// Case 7: New range extends from previous range past the
|
||||
// end of the current range
|
||||
ranges.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ChainingContextualSubstitutionTable, Lookup } from '../tables';
|
||||
import { LookupTree } from '../types';
|
||||
import { ILookupTree } from '../types';
|
||||
|
||||
import { listGlyphsByIndex } from './coverage';
|
||||
import { processInputPosition, processLookaheadPosition, processBacktrackPosition, getInputTree, EntryMeta } from './helper';
|
||||
import { processInputPosition, processLookaheadPosition, processBacktrackPosition, getInputTree, IEntryMeta } from './helper';
|
||||
|
||||
/**
|
||||
* Build lookup tree for GSUB lookup table 6, format 1.
|
||||
@@ -12,8 +12,8 @@ import { processInputPosition, processLookaheadPosition, processBacktrackPositio
|
||||
* @param lookups List of lookup tables
|
||||
* @param tableIndex Index of this table in the overall lookup
|
||||
*/
|
||||
export default function buildTree(table: ChainingContextualSubstitutionTable.Format1, lookups: Lookup[], tableIndex: number): LookupTree {
|
||||
const result: LookupTree = {
|
||||
export default function buildTree(table: ChainingContextualSubstitutionTable.IFormat1, lookups: Lookup[], tableIndex: number): ILookupTree {
|
||||
const result: ILookupTree = {
|
||||
individual: {},
|
||||
range: []
|
||||
};
|
||||
@@ -29,7 +29,7 @@ export default function buildTree(table: ChainingContextualSubstitutionTable.For
|
||||
}
|
||||
|
||||
for (const [subIndex, subTable] of chainRuleSet.entries()) {
|
||||
let currentEntries: EntryMeta[] = getInputTree(
|
||||
let currentEntries: IEntryMeta[] = getInputTree(
|
||||
result,
|
||||
subTable.lookupRecords,
|
||||
lookups,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ChainingContextualSubstitutionTable, Lookup } from '../tables';
|
||||
import { LookupTree } from '../types';
|
||||
import { ILookupTree } from '../types';
|
||||
import mergeTrees from '../merge';
|
||||
|
||||
import { listGlyphsByIndex } from './coverage';
|
||||
import getGlyphClass, { listClassGlyphs } from './classDef';
|
||||
import { processInputPosition, processLookaheadPosition, processBacktrackPosition, getInputTree, EntryMeta } from './helper';
|
||||
import { processInputPosition, processLookaheadPosition, processBacktrackPosition, getInputTree, IEntryMeta } from './helper';
|
||||
|
||||
/**
|
||||
* Build lookup tree for GSUB lookup table 6, format 2.
|
||||
@@ -14,8 +14,8 @@ import { processInputPosition, processLookaheadPosition, processBacktrackPositio
|
||||
* @param lookups List of lookup tables
|
||||
* @param tableIndex Index of this table in the overall lookup
|
||||
*/
|
||||
export default function buildTree(table: ChainingContextualSubstitutionTable.Format2, lookups: Lookup[], tableIndex: number): LookupTree {
|
||||
const results: LookupTree[] = [];
|
||||
export default function buildTree(table: ChainingContextualSubstitutionTable.IFormat2, lookups: Lookup[], tableIndex: number): ILookupTree {
|
||||
const results: ILookupTree[] = [];
|
||||
|
||||
const firstGlyphs = listGlyphsByIndex(table.coverage);
|
||||
|
||||
@@ -35,12 +35,12 @@ export default function buildTree(table: ChainingContextualSubstitutionTable.For
|
||||
}
|
||||
|
||||
for (const [subIndex, subTable] of classSet.entries()) {
|
||||
const result: LookupTree = {
|
||||
const result: ILookupTree = {
|
||||
individual: {},
|
||||
range: []
|
||||
};
|
||||
|
||||
let currentEntries: EntryMeta[] = getInputTree(
|
||||
let currentEntries: IEntryMeta[] = getInputTree(
|
||||
result,
|
||||
subTable.lookupRecords,
|
||||
lookups,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ChainingContextualSubstitutionTable, Lookup } from '../tables';
|
||||
import { LookupTree } from '../types';
|
||||
import { ILookupTree } from '../types';
|
||||
|
||||
import { listGlyphsByIndex } from './coverage';
|
||||
import { processInputPosition, processLookaheadPosition, processBacktrackPosition, getInputTree, EntryMeta } from './helper';
|
||||
import { processInputPosition, processLookaheadPosition, processBacktrackPosition, getInputTree, IEntryMeta } from './helper';
|
||||
|
||||
/**
|
||||
* Build lookup tree for GSUB lookup table 6, format 3.
|
||||
@@ -12,8 +12,8 @@ import { processInputPosition, processLookaheadPosition, processBacktrackPositio
|
||||
* @param lookups List of lookup tables
|
||||
* @param tableIndex Index of this table in the overall lookup
|
||||
*/
|
||||
export default function buildTree(table: ChainingContextualSubstitutionTable.Format3, lookups: Lookup[], tableIndex: number): LookupTree {
|
||||
const result: LookupTree = {
|
||||
export default function buildTree(table: ChainingContextualSubstitutionTable.IFormat3, lookups: Lookup[], tableIndex: number): ILookupTree {
|
||||
const result: ILookupTree = {
|
||||
individual: {},
|
||||
range: []
|
||||
};
|
||||
@@ -21,7 +21,7 @@ export default function buildTree(table: ChainingContextualSubstitutionTable.For
|
||||
const firstGlyphs = listGlyphsByIndex(table.inputCoverage[0]);
|
||||
|
||||
for (const { glyphId } of firstGlyphs) {
|
||||
let currentEntries: EntryMeta[] = getInputTree(
|
||||
let currentEntries: IEntryMeta[] = getInputTree(
|
||||
result,
|
||||
table.lookupRecords,
|
||||
lookups,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ReverseChainingContextualSingleSubstitutionTable } from '../tables';
|
||||
import { LookupTree, LookupTreeEntry } from '../types';
|
||||
import { IReverseChainingContextualSingleSubstitutionTable } from '../tables';
|
||||
import { ILookupTree, ILookupTreeEntry } from '../types';
|
||||
|
||||
import { listGlyphsByIndex } from './coverage';
|
||||
import { processLookaheadPosition, processBacktrackPosition, EntryMeta } from './helper';
|
||||
import { processLookaheadPosition, processBacktrackPosition, IEntryMeta } from './helper';
|
||||
|
||||
/**
|
||||
* Build lookup tree for GSUB lookup table 8, format 1.
|
||||
@@ -11,8 +11,8 @@ import { processLookaheadPosition, processBacktrackPosition, EntryMeta } from '.
|
||||
* @param table JSON representation of the table
|
||||
* @param tableIndex Index of this table in the overall lookup
|
||||
*/
|
||||
export default function buildTree(table: ReverseChainingContextualSingleSubstitutionTable, tableIndex: number): LookupTree {
|
||||
const result: LookupTree = {
|
||||
export default function buildTree(table: IReverseChainingContextualSingleSubstitutionTable, tableIndex: number): ILookupTree {
|
||||
const result: ILookupTree = {
|
||||
individual: {},
|
||||
range: []
|
||||
};
|
||||
@@ -20,7 +20,7 @@ export default function buildTree(table: ReverseChainingContextualSingleSubstitu
|
||||
const glyphs = listGlyphsByIndex(table.coverage);
|
||||
|
||||
for (const { glyphId, index } of glyphs) {
|
||||
const initialEntry: LookupTreeEntry = {};
|
||||
const initialEntry: ILookupTreeEntry = {};
|
||||
if (Array.isArray(glyphId)) {
|
||||
result.range.push({
|
||||
entry: initialEntry,
|
||||
@@ -30,7 +30,7 @@ export default function buildTree(table: ReverseChainingContextualSingleSubstitu
|
||||
result.individual[glyphId] = initialEntry;
|
||||
}
|
||||
|
||||
let currentEntries: EntryMeta[] = [{
|
||||
let currentEntries: IEntryMeta[] = [{
|
||||
entry: initialEntry,
|
||||
substitutions: [table.substitutes[index]]
|
||||
}];
|
||||
|
||||
@@ -13,21 +13,20 @@ export default function getGlyphClass(table: ClassDefTable, glyphId: number | [n
|
||||
case 2:
|
||||
if (Array.isArray(glyphId)) {
|
||||
return getRangeGlyphClass(table, glyphId);
|
||||
} else {
|
||||
return new Map([[
|
||||
glyphId,
|
||||
getIndividualGlyphClass(table, glyphId)
|
||||
]]);
|
||||
}
|
||||
return new Map([[
|
||||
glyphId,
|
||||
getIndividualGlyphClass(table, glyphId)
|
||||
]]);
|
||||
// https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-1
|
||||
default:
|
||||
return new Map([[glyphId, null]]);
|
||||
}
|
||||
}
|
||||
|
||||
function getRangeGlyphClass(table: ClassDefTable.Format2, glyphId: [number, number]): Map<number | [number, number], number | null> {
|
||||
let classStart: number = glyphId[0];
|
||||
let currentClass: number | null = getIndividualGlyphClass(table, classStart);
|
||||
function getRangeGlyphClass(table: ClassDefTable.IFormat2, glyphId: [number, number]): Map<number | [number, number], number | null> {
|
||||
const classStart: number = glyphId[0];
|
||||
const currentClass: number | null = getIndividualGlyphClass(table, classStart);
|
||||
let search: number = glyphId[0] + 1;
|
||||
|
||||
const result = new Map<[number, number] | number, number | null>();
|
||||
@@ -53,7 +52,7 @@ function getRangeGlyphClass(table: ClassDefTable.Format2, glyphId: [number, numb
|
||||
return result;
|
||||
}
|
||||
|
||||
function getIndividualGlyphClass(table: ClassDefTable.Format2, glyphId: number): number | null {
|
||||
function getIndividualGlyphClass(table: ClassDefTable.IFormat2, glyphId: number): number | null {
|
||||
for (const range of table.ranges) {
|
||||
if (range.start <= glyphId && range.end >= glyphId) {
|
||||
return range.classId;
|
||||
|
||||
@@ -25,12 +25,12 @@ export default function getCoverageGlyphIndex(table: CoverageTable, glyphId: num
|
||||
}
|
||||
}
|
||||
|
||||
export function listGlyphsByIndex(table: CoverageTable): { glyphId: number | [number, number]; index: number; }[] {
|
||||
export function listGlyphsByIndex(table: CoverageTable): { glyphId: number | [number, number], index: number }[] {
|
||||
switch (table.format) {
|
||||
case 1:
|
||||
return table.glyphs.map((glyphId, index) => ({ glyphId, index }));
|
||||
case 2:
|
||||
let results: { glyphId: number | [number, number]; index: number; }[] = [];
|
||||
const results: { glyphId: number | [number, number], index: number }[] = [];
|
||||
for (const [index, range] of table.ranges.entries()) {
|
||||
if (range.end === range.start) {
|
||||
results.push({ glyphId: range.start, index });
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { LookupTreeEntry, LookupTree } from '../types';
|
||||
import { SubstitutionLookupRecord, Lookup } from '../tables';
|
||||
import { ILookupTreeEntry, ILookupTree } from '../types';
|
||||
import { ISubstitutionLookupRecord, Lookup } from '../tables';
|
||||
|
||||
import { getIndividualSubstitutionGlyph, getRangeSubstitutionGlyphs } from './substitution';
|
||||
|
||||
export interface EntryMeta {
|
||||
entry: LookupTreeEntry;
|
||||
export interface IEntryMeta {
|
||||
entry: ILookupTreeEntry;
|
||||
substitutions: (number | null)[];
|
||||
}
|
||||
|
||||
export function processInputPosition(
|
||||
glyphs: (number | [number, number])[],
|
||||
position: number,
|
||||
currentEntries: EntryMeta[],
|
||||
lookupRecords: SubstitutionLookupRecord[],
|
||||
currentEntries: IEntryMeta[],
|
||||
lookupRecords: ISubstitutionLookupRecord[],
|
||||
lookups: Lookup[]
|
||||
): EntryMeta[] {
|
||||
const nextEntries: EntryMeta[] = [];
|
||||
): IEntryMeta[] {
|
||||
const nextEntries: IEntryMeta[] = [];
|
||||
for (const currentEntry of currentEntries) {
|
||||
currentEntry.entry.forward = {
|
||||
individual: {},
|
||||
@@ -40,12 +40,12 @@ export function processInputPosition(
|
||||
|
||||
export function processLookaheadPosition(
|
||||
glyphs: (number | [number, number])[],
|
||||
currentEntries: EntryMeta[]
|
||||
): EntryMeta[] {
|
||||
const nextEntries: EntryMeta[] = [];
|
||||
currentEntries: IEntryMeta[]
|
||||
): IEntryMeta[] {
|
||||
const nextEntries: IEntryMeta[] = [];
|
||||
for (const currentEntry of currentEntries) {
|
||||
for (const glyph of glyphs) {
|
||||
const entry: LookupTreeEntry = {};
|
||||
const entry: ILookupTreeEntry = {};
|
||||
if (!currentEntry.entry.forward) {
|
||||
currentEntry.entry.forward = {
|
||||
individual: {},
|
||||
@@ -73,12 +73,12 @@ export function processLookaheadPosition(
|
||||
|
||||
export function processBacktrackPosition(
|
||||
glyphs: (number | [number, number])[],
|
||||
currentEntries: EntryMeta[]
|
||||
): EntryMeta[] {
|
||||
const nextEntries: EntryMeta[] = [];
|
||||
currentEntries: IEntryMeta[]
|
||||
): IEntryMeta[] {
|
||||
const nextEntries: IEntryMeta[] = [];
|
||||
for (const currentEntry of currentEntries) {
|
||||
for (const glyph of glyphs) {
|
||||
const entry: LookupTreeEntry = {};
|
||||
const entry: ILookupTreeEntry = {};
|
||||
if (!currentEntry.entry.reverse) {
|
||||
currentEntry.entry.reverse = {
|
||||
individual: {},
|
||||
@@ -104,8 +104,8 @@ export function processBacktrackPosition(
|
||||
return nextEntries;
|
||||
}
|
||||
|
||||
export function getInputTree(tree: LookupTree, substitutions: SubstitutionLookupRecord[], lookups: Lookup[], inputIndex: number, glyphId: number | [number, number]): { entry: LookupTreeEntry; substitution: number | null; }[] {
|
||||
const result: { entry: LookupTreeEntry; substitution: number | null; }[] = [];
|
||||
export function getInputTree(tree: ILookupTree, substitutions: ISubstitutionLookupRecord[], lookups: Lookup[], inputIndex: number, glyphId: number | [number, number]): { entry: ILookupTreeEntry, substitution: number | null }[] {
|
||||
const result: { entry: ILookupTreeEntry, substitution: number | null }[] = [];
|
||||
if (!Array.isArray(glyphId)) {
|
||||
tree.individual[glyphId] = {};
|
||||
result.push({
|
||||
@@ -115,7 +115,7 @@ export function getInputTree(tree: LookupTree, substitutions: SubstitutionLookup
|
||||
} else {
|
||||
const subs = getSubstitutionAtPositionRange(substitutions, lookups, inputIndex, glyphId);
|
||||
for (const [range, substitution] of subs) {
|
||||
const entry: LookupTreeEntry = {};
|
||||
const entry: ILookupTreeEntry = {};
|
||||
if (Array.isArray(range)) {
|
||||
tree.range.push({ range, entry });
|
||||
} else {
|
||||
@@ -128,9 +128,9 @@ export function getInputTree(tree: LookupTree, substitutions: SubstitutionLookup
|
||||
return result;
|
||||
}
|
||||
|
||||
function getSubstitutionAtPositionRange(substitutions: SubstitutionLookupRecord[], lookups: Lookup[], index: number, range: [number, number]): Map<number | [number, number], number | null> {
|
||||
function getSubstitutionAtPositionRange(substitutions: ISubstitutionLookupRecord[], lookups: Lookup[], index: number, range: [number, number]): Map<number | [number, number], number | null> {
|
||||
for (const substitution of substitutions.filter(s => s.sequenceIndex === index)) {
|
||||
for (const substitutionTable of (lookups[substitution.lookupListIndex] as Lookup.Type1).subtables) {
|
||||
for (const substitutionTable of (lookups[substitution.lookupListIndex] as Lookup.IType1).subtables) {
|
||||
const sub = getRangeSubstitutionGlyphs(
|
||||
substitutionTable,
|
||||
range
|
||||
@@ -145,9 +145,9 @@ function getSubstitutionAtPositionRange(substitutions: SubstitutionLookupRecord[
|
||||
return new Map([[range, null]]);
|
||||
}
|
||||
|
||||
function getSubstitutionAtPosition(substitutions: SubstitutionLookupRecord[], lookups: Lookup[], index: number, glyphId: number): number | null {
|
||||
function getSubstitutionAtPosition(substitutions: ISubstitutionLookupRecord[], lookups: Lookup[], index: number, glyphId: number): number | null {
|
||||
for (const substitution of substitutions.filter(s => s.sequenceIndex === index)) {
|
||||
for (const substitutionTable of (lookups[substitution.lookupListIndex] as Lookup.Type1).subtables) {
|
||||
for (const substitutionTable of (lookups[substitution.lookupListIndex] as Lookup.IType1).subtables) {
|
||||
const sub = getIndividualSubstitutionGlyph(
|
||||
substitutionTable,
|
||||
glyphId
|
||||
|
||||
@@ -10,8 +10,8 @@ import getCoverageGlyphIndex from './coverage';
|
||||
* @param glyphId The index of the glpyh to find substitutions for
|
||||
*/
|
||||
export function getRangeSubstitutionGlyphs(table: SubstitutionTable, glyphId: [number, number]): Map<[number, number] | number, number | null> {
|
||||
let replacementStart: number = glyphId[0];
|
||||
let currentReplacement: number | null = getIndividualSubstitutionGlyph(table, replacementStart);
|
||||
const replacementStart: number = glyphId[0];
|
||||
const currentReplacement: number | null = getIndividualSubstitutionGlyph(table, replacementStart);
|
||||
let search: number = glyphId[0] + 1;
|
||||
|
||||
const result = new Map<[number, number] | number, number | null>();
|
||||
@@ -54,7 +54,7 @@ export function getIndividualSubstitutionGlyph(table: SubstitutionTable, glyphId
|
||||
return (glyphId + table.deltaGlyphId) % (2 ** 16);
|
||||
// https://docs.microsoft.com/en-us/typography/opentype/spec/gsub#12-single-substitution-format-2
|
||||
case 2:
|
||||
// tslint:disable-next-line
|
||||
// eslint-disable-next-line eqeqeq
|
||||
return table.substitute[coverageIndex] != null
|
||||
? table.substitute[coverageIndex]
|
||||
: null;
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
export type SubstitutionTable = SubstitutionTable.Format1 | SubstitutionTable.Format2;
|
||||
export type SubstitutionTable = SubstitutionTable.IFormat1 | SubstitutionTable.IFormat2;
|
||||
export namespace SubstitutionTable {
|
||||
export interface Format1 {
|
||||
export interface IFormat1 {
|
||||
substFormat: 1;
|
||||
coverage: CoverageTable;
|
||||
deltaGlyphId: number;
|
||||
}
|
||||
|
||||
export interface Format2 {
|
||||
export interface IFormat2 {
|
||||
substFormat: 2;
|
||||
coverage: CoverageTable;
|
||||
substitute: number[];
|
||||
}
|
||||
}
|
||||
|
||||
export type CoverageTable = CoverageTable.Format1 | CoverageTable.Format2;
|
||||
export type CoverageTable = CoverageTable.IFormat1 | CoverageTable.IFormat2;
|
||||
export namespace CoverageTable {
|
||||
export interface Format1 {
|
||||
export interface IFormat1 {
|
||||
format: 1;
|
||||
glyphs: number[];
|
||||
}
|
||||
|
||||
export interface Format2 {
|
||||
export interface IFormat2 {
|
||||
format: 2;
|
||||
ranges: {
|
||||
start: number;
|
||||
@@ -30,34 +30,34 @@ export namespace CoverageTable {
|
||||
}
|
||||
}
|
||||
|
||||
export type ChainingContextualSubstitutionTable = ChainingContextualSubstitutionTable.Format1 |
|
||||
ChainingContextualSubstitutionTable.Format2 | ChainingContextualSubstitutionTable.Format3;
|
||||
export type ChainingContextualSubstitutionTable = ChainingContextualSubstitutionTable.IFormat1 |
|
||||
ChainingContextualSubstitutionTable.IFormat2 | ChainingContextualSubstitutionTable.IFormat3;
|
||||
export namespace ChainingContextualSubstitutionTable {
|
||||
export interface Format1 {
|
||||
export interface IFormat1 {
|
||||
substFormat: 1;
|
||||
coverage: CoverageTable;
|
||||
chainRuleSets: ChainSubRuleTable[][];
|
||||
}
|
||||
|
||||
export interface Format2 {
|
||||
export interface IFormat2 {
|
||||
substFormat: 2;
|
||||
coverage: CoverageTable;
|
||||
backtrackClassDef: ClassDefTable;
|
||||
inputClassDef: ClassDefTable;
|
||||
lookaheadClassDef: ClassDefTable;
|
||||
chainClassSet: (null | ChainSubClassRuleTable[])[];
|
||||
chainClassSet: (null | IChainSubClassRuleTable[])[];
|
||||
}
|
||||
|
||||
export interface Format3 {
|
||||
export interface IFormat3 {
|
||||
substFormat: 3;
|
||||
backtrackCoverage: CoverageTable[];
|
||||
inputCoverage: CoverageTable[];
|
||||
lookaheadCoverage: CoverageTable[];
|
||||
lookupRecords: SubstitutionLookupRecord[];
|
||||
lookupRecords: ISubstitutionLookupRecord[];
|
||||
}
|
||||
}
|
||||
|
||||
export interface ReverseChainingContextualSingleSubstitutionTable {
|
||||
export interface IReverseChainingContextualSingleSubstitutionTable {
|
||||
substFormat: 1;
|
||||
coverage: CoverageTable;
|
||||
backtrackCoverage: CoverageTable[];
|
||||
@@ -65,9 +65,9 @@ export interface ReverseChainingContextualSingleSubstitutionTable {
|
||||
substitutes: number[];
|
||||
}
|
||||
|
||||
export type ClassDefTable = ClassDefTable.Format2;
|
||||
export type ClassDefTable = ClassDefTable.IFormat2;
|
||||
export namespace ClassDefTable {
|
||||
export interface Format2 {
|
||||
export interface IFormat2 {
|
||||
format: 2;
|
||||
ranges: {
|
||||
start: number;
|
||||
@@ -77,36 +77,36 @@ export namespace ClassDefTable {
|
||||
}
|
||||
}
|
||||
|
||||
export interface SubstitutionLookupRecord {
|
||||
export interface ISubstitutionLookupRecord {
|
||||
sequenceIndex: number;
|
||||
lookupListIndex: number;
|
||||
}
|
||||
|
||||
export type ChainSubRuleTable = ChainSubClassRuleTable;
|
||||
export interface ChainSubClassRuleTable {
|
||||
export type ChainSubRuleTable = IChainSubClassRuleTable;
|
||||
export interface IChainSubClassRuleTable {
|
||||
backtrack: number[];
|
||||
input: number[];
|
||||
lookahead: number[];
|
||||
lookupRecords: SubstitutionLookupRecord[];
|
||||
lookupRecords: ISubstitutionLookupRecord[];
|
||||
}
|
||||
|
||||
export type Lookup = Lookup.Type1 | Lookup.Type6 | Lookup.Type8;
|
||||
export type Lookup = Lookup.IType1 | Lookup.IType6 | Lookup.IType8;
|
||||
export namespace Lookup {
|
||||
export interface Type1 {
|
||||
export interface IType1 {
|
||||
lookupType: 1;
|
||||
lookupFlag: number;
|
||||
subtables: SubstitutionTable[];
|
||||
}
|
||||
|
||||
export interface Type6 {
|
||||
export interface IType6 {
|
||||
lookupType: 6;
|
||||
lookupFlag: number;
|
||||
subtables: ChainingContextualSubstitutionTable[];
|
||||
}
|
||||
|
||||
export interface Type8 {
|
||||
export interface IType8 {
|
||||
lookupType: 8;
|
||||
lookupFlag: number;
|
||||
subtables: ReverseChainingContextualSingleSubstitutionTable[];
|
||||
subtables: IReverseChainingContextualSingleSubstitutionTable[];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export interface SubstitutionResult {
|
||||
export interface ISubstitutionResult {
|
||||
index: number;
|
||||
contextRange: [number, number];
|
||||
}
|
||||
@@ -6,7 +6,7 @@ export interface SubstitutionResult {
|
||||
/**
|
||||
* Information about ligatures found in a sequence of text
|
||||
*/
|
||||
export interface LigatureData {
|
||||
export interface ILigatureData {
|
||||
/**
|
||||
* The list of font glyphs in the input text.
|
||||
*/
|
||||
@@ -25,14 +25,14 @@ export interface LigatureData {
|
||||
contextRanges: [number, number][];
|
||||
}
|
||||
|
||||
export interface Font {
|
||||
export interface IFont {
|
||||
/**
|
||||
* Scans the provided text for font ligatures, returning an object with
|
||||
* metadata about the text and any ligatures found.
|
||||
*
|
||||
* @param text String to search for ligatures
|
||||
*/
|
||||
findLigatures(text: string): LigatureData;
|
||||
findLigatures(text: string): ILigatureData;
|
||||
|
||||
/**
|
||||
* Scans the provided text for font ligatures, returning an array of ranges
|
||||
@@ -43,7 +43,7 @@ export interface Font {
|
||||
findLigatureRanges(text: string): [number, number][];
|
||||
}
|
||||
|
||||
export interface Options {
|
||||
export interface IOptions {
|
||||
/**
|
||||
* Optional size of previous results to store, measured in total number of
|
||||
* characters from input strings. Defaults to no cache (0)
|
||||
@@ -51,23 +51,23 @@ export interface Options {
|
||||
cacheSize?: number;
|
||||
}
|
||||
|
||||
export interface LookupTree {
|
||||
export interface ILookupTree {
|
||||
individual: {
|
||||
[glyphId: string]: LookupTreeEntry;
|
||||
[glyphId: string]: ILookupTreeEntry;
|
||||
};
|
||||
range: {
|
||||
range: [number, number];
|
||||
entry: LookupTreeEntry;
|
||||
entry: ILookupTreeEntry;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface LookupTreeEntry {
|
||||
lookup?: LookupResult;
|
||||
forward?: LookupTree;
|
||||
reverse?: LookupTree;
|
||||
export interface ILookupTreeEntry {
|
||||
lookup?: ILookupResult;
|
||||
forward?: ILookupTree;
|
||||
reverse?: ILookupTree;
|
||||
}
|
||||
|
||||
export interface LookupResult {
|
||||
export interface ILookupResult {
|
||||
substitutions: (number | null)[];
|
||||
length: number;
|
||||
index: number;
|
||||
@@ -75,12 +75,12 @@ export interface LookupResult {
|
||||
contextRange: [number, number];
|
||||
}
|
||||
|
||||
export interface FlattenedLookupTree {
|
||||
[glyphId: string]: FlattenedLookupTreeEntry;
|
||||
export interface IFlattenedLookupTree {
|
||||
[glyphId: string]: IFlattenedLookupTreeEntry;
|
||||
}
|
||||
|
||||
export interface FlattenedLookupTreeEntry {
|
||||
lookup?: LookupResult;
|
||||
forward?: FlattenedLookupTree;
|
||||
reverse?: FlattenedLookupTree;
|
||||
export interface IFlattenedLookupTreeEntry {
|
||||
lookup?: ILookupResult;
|
||||
forward?: IFlattenedLookupTree;
|
||||
reverse?: IFlattenedLookupTree;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { FlattenedLookupTree, LookupResult } from './types';
|
||||
import { IFlattenedLookupTree, ILookupResult } from './types';
|
||||
|
||||
export default function walkTree(tree: FlattenedLookupTree, sequence: number[], startIndex: number, index: number): LookupResult | undefined {
|
||||
export default function walkTree(tree: IFlattenedLookupTree, sequence: number[], startIndex: number, index: number): ILookupResult | undefined {
|
||||
const glyphId = sequence[index];
|
||||
let subtree = tree[glyphId];
|
||||
const subtree = tree[glyphId];
|
||||
if (!subtree) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -45,9 +45,9 @@ export default function walkTree(tree: FlattenedLookupTree, sequence: number[],
|
||||
return lookup;
|
||||
}
|
||||
|
||||
function walkReverse(tree: FlattenedLookupTree, sequence: number[], index: number): LookupResult | undefined {
|
||||
function walkReverse(tree: IFlattenedLookupTree, sequence: number[], index: number): ILookupResult | undefined {
|
||||
let subtree = tree[sequence[--index]];
|
||||
let lookup: LookupResult | undefined = subtree && subtree.lookup;
|
||||
let lookup: ILookupResult | undefined = subtree && subtree.lookup;
|
||||
while (subtree) {
|
||||
if (
|
||||
(!lookup && subtree.lookup) ||
|
||||
|
||||
Reference in New Issue
Block a user