Skip to content

Commit

Permalink
WIP Add patcher to templorarily patch existing properties until they …
Browse files Browse the repository at this point in the history
…are solved by MDN
  • Loading branch information
frenic committed Apr 13, 2018
1 parent de00002 commit f412962
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 25 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"@types/jest": "^22.1.1",
"@types/node": "^9.4.2",
"@types/prettier": "^1.10.0",
"chalk": "^2.3.2",
"chokidar": "^2.0.0",
"flow-bin": "^0.69.0",
"jest": "^22.2.1",
Expand Down
24 changes: 18 additions & 6 deletions src/data-types.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import * as properties from 'mdn-data/css/properties.json';
import * as syntaxes from 'mdn-data/css/syntaxes.json';
import { compatPropertySyntax } from './compat';
import parse from './parser';
import typing, { addType, DataType, hasType, ResolvedType, Type, TypeType } from './typer';

const MIN_TYPES = 3;

const dataTypes: { [key: string]: ResolvedType[] } = {};

export default dataTypes;

export function resolveDataTypes(
types: TypeType[],
resolver: (name: string) => ResolvedType[] = dataTypeResolver,
resolver: (name: string) => ResolvedType[] = simpleDataTypeResolver,
min = 3,
): ResolvedType[] {
let resolvedDataTypes: ResolvedType[] = [];

Expand All @@ -19,7 +20,7 @@ export function resolveDataTypes(
case Type.DataType: {
const resolvedDataType = resolver(type.name);

if (resolvedDataType.length >= MIN_TYPES) {
if (resolvedDataType.length >= min) {
// Dissolve data type if it's too small
resolvedDataTypes = addType(resolvedDataTypes, addDataType(type.name, resolvedDataType));
} else {
Expand All @@ -46,12 +47,23 @@ export function resolveDataTypes(
return resolvedDataTypes;
}

function dataTypeResolver(name: string): ResolvedType[] {
function simpleDataTypeResolver(name: string): ResolvedType[] {
return name in syntaxes
? resolveDataTypes(typing(parse(syntaxes[name].syntax)), dataTypeResolver)
? resolveDataTypes(typing(parse(syntaxes[name].syntax)), simpleDataTypeResolver)
: [{ type: Type.String }];
}

export function createPropertyDataTypeResolver(propertyName: string, min?: number) {
const resolver: (dataTypeName: string) => ResolvedType[] = dataTypeName => {
const data = syntaxes[dataTypeName] || properties[dataTypeName];
return data
? resolveDataTypes(typing(compatPropertySyntax(propertyName, parse(data.syntax))), resolver, min)
: [{ type: Type.String }];
};

return resolver;
}

function addDataType(name: string, types: ResolvedType[], index = 0): DataType {
const realName = name + (index > 0 ? index + 1 : '');

Expand Down
1 change: 1 addition & 0 deletions src/data/css-patches.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const properties: { [property: string]: Pick<MDN.Property, 'syntax'> } = {};
104 changes: 104 additions & 0 deletions src/patcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import chalk from 'chalk';
import { createPropertyDataTypeResolver, resolveDataTypes } from './data-types';
import { properties as propertyPatches } from './data/css-patches';
import parse from './parser';
import typing, { addType, hasType, ResolvedType, Type } from './typer';

export default function patchProperty(name: string, types: ResolvedType[]): ResolvedType[] {
if (!(name in propertyPatches)) {
// Nothing to patch
return types;
}

// Dissolve all data types to check whether it already exists or not
const dissolvedTypes = resolveDataTypes(types, createPropertyDataTypeResolver(name, Infinity), Infinity);
const patchTypes = typing(parse(propertyPatches[name].syntax));

let patchedTypes = types;

for (const type of patchTypes) {
if (!hasType(dissolvedTypes, type)) {
patchedTypes = addType(patchedTypes, type);

switch (type.type) {
case Type.DataType:
info('The property syntax patch with data type `<%s>` for property `%s` was added', type.name, name);
break;
case Type.Length:
info('The property syntax patch with `<length>` for property `%s` was added', name);
break;
case Type.String:
info('The property syntax patch resolved to `string` for property `%s` was added', name);
break;
case Type.Number:
info('The property syntax patch resolved to `number` for property `%s` was added', name);
break;
case Type.NumericLiteral:
case Type.StringLiteral:
info('The property syntax patch with keyword `%s` for property `%s` was added', String(type.literal), name);
break;
default:
info('A property syntax patch for property `%s` was added', name);
}
} else {
switch (type.type) {
case Type.DataType:
error(
'The property syntax patch with data type `<%s>` for property `%s` was ignored ' +
'because it has been fixed permanently and must be removed',
type.name,
name,
);
break;
case Type.Length:
error(
'The property syntax patch with `<length>` for property `%s` was ignored ' +
'because it has been fixed permanently and must be removed',
name,
);
break;
case Type.String:
error(
'The property syntax patch resolved to `string` for property `%s` was ignored ' +
'because it has been fixed permanently and must be removed',
name,
);
break;
case Type.Number:
error(
'The property syntax patch resolved to `number` for property `%s` was ignored ' +
'because it has been fixed permanently and must be removed',
name,
);
break;
case Type.NumericLiteral:
case Type.StringLiteral:
error(
'The property syntax patch with keyword `%s` for property `%s` was ignored ' +
'because it has been fixed permanently and must be removed',
String(type.literal),
name,
);
break;
default:
error(
'A property syntax patch for property `%s` was ignored because it has been fixed ' +
'permanently and must be removed',
name,
);
}
}
}

return patchedTypes;
}

const error: typeof console.error = (message, ...params) => {
// Complete the build process but exit with failure when done
process.exitCode = 1;
console.error(chalk.magenta('ERROR! ' + message), ...params);
};

const info: typeof console.info = (message, ...params) => {
console.info(chalk.cyan(message), ...params);
};
28 changes: 10 additions & 18 deletions src/properties.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as properties from 'mdn-data/css/properties.json';
import * as syntaxes from 'mdn-data/css/syntaxes.json';
import { compatPropertyNames, compatPropertySyntax, isDeprecated } from './compat';
import { resolveDataTypes } from './data-types';
import { createPropertyDataTypeResolver, resolveDataTypes } from './data-types';
import { properties as rawSvgProperties, syntaxes as svgSyntaxes } from './data/svg';
import parse from './parser';
import typing, { ResolvedType, Type } from './typer';
import patchProperty from './patcher';
import typing, { ResolvedType } from './typer';

const IGNORES = [
// Custom properties
Expand Down Expand Up @@ -44,9 +44,12 @@ for (const originalName in properties) {

const property: IProperty = {
name: originalName,
types: resolveDataTypes(
typing(compatPropertySyntax(originalName, parse(properties[originalName].syntax))),
createDataTypeResolver(originalName),
types: patchProperty(
originalName,
resolveDataTypes(
typing(compatPropertySyntax(originalName, parse(properties[originalName].syntax))),
createPropertyDataTypeResolver(originalName),
),
),
};

Expand Down Expand Up @@ -91,17 +94,6 @@ for (const name in rawSvgProperties) {
}
}

export function createDataTypeResolver(propertyName: string) {
const resolver: (dataTypeName: string) => ResolvedType[] = dataTypeName => {
const data = syntaxes[dataTypeName] || properties[dataTypeName];
return data
? resolveDataTypes(typing(compatPropertySyntax(propertyName, parse(data.syntax))), resolver)
: [{ type: Type.String }];
};

return resolver;
}

export function isVendorProperty(name: string) {
return REGEX_VENDOR_PROPERTY.test(name);
}
Expand All @@ -112,7 +104,7 @@ export function filterMissingProperties(propertyNames: string[]) {
}

function createSvgDataTypeResolver(propertyName: string) {
const resolver = createDataTypeResolver(propertyName);
const resolver = createPropertyDataTypeResolver(propertyName);
const svgResolver: (dataTypeName: string) => ResolvedType[] = (dataTypeName: string) =>
dataTypeName in svgSyntaxes
? resolveDataTypes(typing(parse(svgSyntaxes[dataTypeName].syntax)), svgResolver)
Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"

chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0:
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
dependencies:
Expand Down

0 comments on commit f412962

Please sign in to comment.