Skip to content

Commit

Permalink
feat: support curly braces multipliers for groups and map infinite mu…
Browse files Browse the repository at this point in the history
…ltipliers to capped finite versions, fixes #2 (#13)
  • Loading branch information
johanneslumpe authored Nov 24, 2018
1 parent ee24316 commit 347f251
Show file tree
Hide file tree
Showing 10 changed files with 851 additions and 77 deletions.
779 changes: 751 additions & 28 deletions generated/types.ts

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/generateIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import ts from 'typescript';
import * as util from 'util';
import { TYPES_BUILD_DIR } from './constants';

/**
* Generates the main index file with all exports
* @param filenames The filename of the files of which to export all named export
*/
export function generateIndex(filenames: string[]) {
const printer = ts.createPrinter({
newLine: ts.NewLineKind.LineFeed,
Expand Down
5 changes: 5 additions & 0 deletions src/generateTypeNodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ export const generateTypesNodes = (
flatMap(item => {
if (!Array.isArray(item)) {
return generateTypesNodes([item]);
} else if (
// we have to preserve unions within tuples
item.representation === ComponentTypeRepresentation.UNION
) {
return generateTypesNodes(item);
}

// nested tuple nodes need to be lifted up into their parent tuples
Expand Down
43 changes: 5 additions & 38 deletions src/generateTypesFromRawSyntaxes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
RawToken,
SyntaxLookupFn,
} from './types';
import { convertInfiniteMultiplersToFinite } from './utils/convertInfiniteMultiplersToFinite';
import { convertRawTokensToComponents } from './utils/convertRawTokensToComponents';
import { findDataTypeInTree } from './utils/findDataTypeInTree';
import { generateCombinedKeywords } from './utils/generateCombinedKeywords';
Expand Down Expand Up @@ -41,38 +42,6 @@ const appendSuffixToDataTypes = (tokens: RawToken[], suffix: string) => {
}, tokens);
};

// function isPlusMultiplier(token: RawToken) {
// return (
// token.type === ICssTokenType.MULTIPLIER &&
// token.data &&
// token.data.subType === ICssMultiplierTokenType.PLUS
// );
// }
// function isAsteriskMultiplier(token: RawToken) {
// return (
// token.type === ICssTokenType.MULTIPLIER &&
// token.data &&
// token.data.subType === ICssMultiplierTokenType.ASTERISK
// );
// }

// /**
// * Converts infinite multipliers like `+` and `*` to opinionated, finite `{}` versions.
// * Opinionated, because they will have a cap at 10 repetitions
// * @param tokens
// * @param suffix
// */
// function convertInfiniteMultiplersToFinite(tokens: RawToken[]) {
// tokens.forEach(token => {
// const isPlus = isPlusMultiplier(token);
// const isAsterisk = isAsteriskMultiplier(token);
// if (isPlus || isAsterisk) {
// token.data!.subType = ICssMultiplierTokenType.CURLY_BRACES;
// token.value = isPlus ? `{1,9}` : '{0,9}';
// }
// });
// }

const generateTypesForKey = (
key: string,
suffix: string,
Expand Down Expand Up @@ -222,14 +191,12 @@ export const generateTypesFromRawSyntaxes = (
acc.push(combined);
}

/**
* After the combined types we still output the tuple
* types because some people might prefer them and
* it's nice to have both options
*/
appendSuffixToDataTypes(parsedSyntax, typeSuffix);
// convertInfiniteMultiplersToFinite(emittedTokens);
convertInfiniteMultiplersToFinite(parsedSyntax);

// After the combined types we still output the tuple
// types because some people might prefer them and
// it's nice to have both options
try {
const components = convertRawTokensToComponents(parsedSyntax);
const typeCombinations = generateTypeCombinations(
Expand Down
23 changes: 23 additions & 0 deletions src/utils/convertInfiniteMultiplersToFinite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ICssMultiplierTokenType } from '@johanneslumpe/css-value-declaration-grammer-lexer';
import { forEach } from 'lodash/fp';

import { RawToken } from '../types';
import { isAsteriskMultiplier } from './isAsteriskMultiplier';
import { isPlusMultiplier } from './isPlusMultiplier';

/**
* Converts infinite multipliers like `+` and `*` to opinionated, finite `{}` versions.
* Opinionated, because they will be capped at 8 repetitions
* @param tokens
* @param suffix
*/
export function convertInfiniteMultiplersToFinite(tokens: RawToken[]) {
forEach(token => {
const isPlus = isPlusMultiplier(token);
const isAsterisk = isAsteriskMultiplier(token);
if (isPlus || isAsterisk) {
token.data!.subType = ICssMultiplierTokenType.CURLY_BRACES;
token.value = isPlus ? '{1,8}' : '{0,8}';
}
}, tokens);
}
12 changes: 1 addition & 11 deletions src/utils/generateComponentPermutations.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
import { ICssMultiplierTokenType } from '@johanneslumpe/css-value-declaration-grammer-lexer';
import { forEach, reduce } from 'lodash/fp';

import { IComponent, INestedComponentArray } from '../types';
import { generateComponentMultiplierPermutations } from './generateComponentMultiplierPermutations';

function isCurlyBraceMultiplierArray(arr: IComponent[]): boolean {
return arr.every(
component =>
!!(
component.multiplier &&
component.multiplier.type === ICssMultiplierTokenType.CURLY_BRACES
),
);
}
import { isCurlyBraceMultiplierArray } from './isCurlyBraceMultiplierArray';

export function generateComponentPermutations(
arrays: INestedComponentArray[],
Expand Down
21 changes: 21 additions & 0 deletions src/utils/generateTypeCombinations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,27 @@ export function generateTypeCombinations(
generateTypeCombinations(entity.entities),
);

if (
entity.multiplier &&
entity.multiplier.type === ICssMultiplierTokenType.CURLY_BRACES
) {
const arr: INestedComponentArray = [];
for (
let i = entity.multiplier.min;
i <= entity.multiplier.max;
i++
) {
if (i === 1) {
arr.push(combinations);
} else {
const args = new Array(i);
args.fill(createUnionArray(combinations));
arr.push(createTupleArray(args));
}
}
return createUnionArray(arr);
}

const final: INestedComponentArray =
entity.multiplier &&
entity.multiplier.type === ICssMultiplierTokenType.QUESTION_MARK
Expand Down
14 changes: 14 additions & 0 deletions src/utils/isAsteriskMultiplier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {
ICssMultiplierTokenType,
ICssTokenType,
} from '@johanneslumpe/css-value-declaration-grammer-lexer';

import { RawToken } from '../types';

export function isAsteriskMultiplier(token: RawToken) {
return (
token.type === ICssTokenType.MULTIPLIER &&
token.data &&
token.data.subType === ICssMultiplierTokenType.ASTERISK
);
}
13 changes: 13 additions & 0 deletions src/utils/isCurlyBraceMultiplierArray.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ICssMultiplierTokenType } from '@johanneslumpe/css-value-declaration-grammer-lexer';

import { IComponent } from '../types';

export function isCurlyBraceMultiplierArray(arr: IComponent[]): boolean {
return arr.every(
component =>
!!(
component.multiplier &&
component.multiplier.type === ICssMultiplierTokenType.CURLY_BRACES
),
);
}
14 changes: 14 additions & 0 deletions src/utils/isPlusMultiplier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {
ICssMultiplierTokenType,
ICssTokenType,
} from '@johanneslumpe/css-value-declaration-grammer-lexer';

import { RawToken } from '../types';

export function isPlusMultiplier(token: RawToken) {
return (
token.type === ICssTokenType.MULTIPLIER &&
token.data &&
token.data.subType === ICssMultiplierTokenType.PLUS
);
}

0 comments on commit 347f251

Please sign in to comment.