Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autobuild #2

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,7 @@ module.exports = {
},
],
"arrow-parens": ["error", "as-needed"],
"@typescript-eslint/no-namespace": 0,
"@typescript-eslint/no-empty-interface": 0,
},
};
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ tags
.build
yarn-error.log
lib
packages/tacky-css/src/generated
120 changes: 120 additions & 0 deletions packages/tacky-css/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// import * as chokidar from 'chokidar';
import * as fs from "fs";
import * as path from "path";
import * as prettier from "prettier";
import { writeFileAsync } from "./utils";

// import { runCLI } from 'jest';

trigger().then(() => {
process.exit(0);
});

async function trigger(): Promise<void> {
const generatePath = path.resolve("./generate");
for (const key in require.cache) {
if (key.indexOf(generatePath) !== -1) {
delete require.cache[key];
}
}

const outDir = path.resolve("./src/generated");
if (!fs.existsSync(outDir)) {
fs.mkdirSync(outDir);
}

const { default: generateTypescript } = await import("./generate/typescript");
const unformatted = await generateTypescript();

const formatted = await Promise.all(
unformatted.map(async ({ name, content }) => ({
name,
content: await format(content),
}))
);

await Promise.all(
formatted.map(
async ({ name, content }) =>
await writeFileAsync(`./src/generated/${name}`, content)
)
);
}

// if (process.argv.includes('--start')) {
// trigger()
// .then(() => {
// process.exit(0);
// })
// .catch(e => {
// console.error(e);
// process.exit(1);
// });
// } else if (process.argv.includes('--watch')) {
// trigger()
// .catch(e => {
// console.error(e);
// })
// .then(() => {
// console.info('Done! Watching...');
// let debounce: NodeJS.Timer;
// chokidar
// .watch(path.join(__dirname, 'src'), { ignored: '*.json', ignoreInitial: true })
// .on('all', (event: string) => {
// clearTimeout(debounce);
// debounce = setTimeout(
// () =>
// trigger()
// .catch(e => console.error(e))
// .then(() => console.info('Done! Moving on...')),
// 300,
// );
// });
// });
// }

// export default async function trigger() {
// console.info('Generating...');
// const { unformattedFlow, unformattedTypescript } = await create();
// console.info('Formatting...');
// const [flow, typescript] = await Promise.all([
// format(unformattedFlow, 'flow'),
// format(unformattedTypescript, 'typescript'),
// ]);
// console.info(`Writing files...`);
// await Promise.all([writeFileAsync(FLOW_FILENAME, flow), writeFileAsync(TYPESCRIPT_FILENAME, typescript)]);
// console.info('Testing...');
// await testing();
// }

// async function create() {
// const generatePath = path.resolve('./src');
// for (const key in require.cache) {
// if (key.indexOf(generatePath) !== -1) {
// delete require.cache[key];
// }
// }
// const { default: generateFlow } = await import('./src/flow');
// const { default: generateTypescript } = await import('./src/typescript');
// return { unformattedFlow: await generateFlow(), unformattedTypescript: await generateTypescript() };
// }

async function format(output: string): Promise<string> {
const options = await prettier.resolveConfig(
path.join(__dirname, ".prettierrc")
);
try {
return prettier.format(output, {
...options,
printWidth: 180,
singleQuote: false,
parser: "typescript",
});
} catch (e) {
throw new Error(e);
}
}

// function testing() {
// return runCLI({ testMatch: ['**/__tests__/dist.*.ts'] } as any, [__dirname]);
// }
117 changes: 117 additions & 0 deletions packages/tacky-css/generate/collections/data-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import parse from '../syntax/parser';
import typing, { addType, DataType, hasType, IDataType, ResolvedType, Type, TypeType } from '../syntax/typer';
import { compatSyntax } from '../utils/compat';
import { getPropertySyntax, getSyntax } from './syntaxes';

export interface IDataTypeDictionary {
[key: string]: ResolvedType[];
}

export async function getDataTypesOf<TReturn>(dataTypeOf: (dataTypes: IDataTypeDictionary) => Promise<TReturn>) {
const dictionary: IDataTypeDictionary = {};
const result = await dataTypeOf(dictionary);
return [dictionary, result] as const;
}

export async function resolveDataTypes(
dictionary: IDataTypeDictionary,
types: TypeType[],
minTypesInDataTypes: number,
resolver: (
dataTypes: IDataTypeDictionary,
dataType: IDataType,
min: number,
) => Promise<ResolvedType[]> = simpleDataTypeResolver,
): Promise<ResolvedType[]> {
let resolvedDataTypes: ResolvedType[] = [];

for (const type of types) {
switch (type.type) {
case Type.DataType: {
const resolvedDataType = await resolver(dictionary, type, minTypesInDataTypes);

if (resolvedDataType.length >= minTypesInDataTypes) {
// Dissolve data type if it's too small
resolvedDataTypes = addType(resolvedDataTypes, addDataType(dictionary, type.name, resolvedDataType));
} else {
for (const resolvedType of resolvedDataType) {
resolvedDataTypes = addType(resolvedDataTypes, resolvedType);
}
}
break;
}
case Type.PropertyReference: {
const resolvedProperty = await resolver(dictionary, type, minTypesInDataTypes);

// Dissolve property references completely
for (const resolvedType of resolvedProperty) {
resolvedDataTypes = addType(resolvedDataTypes, resolvedType);
}
break;
}
default:
resolvedDataTypes = addType(resolvedDataTypes, type);
}
}

return resolvedDataTypes;
}

async function simpleDataTypeResolver(
dictionary: IDataTypeDictionary,
dataType: IDataType,
minTypesInDataTypes: number,
): Promise<ResolvedType[]> {
const syntax = await getSyntax(dataType.name);
return syntax
? resolveDataTypes(dictionary, typing(parse(syntax)), minTypesInDataTypes, simpleDataTypeResolver)
: [{ type: Type.String }];
}

export function createPropertyDataTypeResolver(data: MDN.CompatData | undefined) {
const resolver: (
dictionary: IDataTypeDictionary,
dataType: IDataType,
min: number,
) => Promise<ResolvedType[]> = async (dictionary, dataType, minTypesInDataTypes) => {
const syntax =
dataType.type === Type.DataType ? await getSyntax(dataType.name) : await getPropertySyntax(dataType.name);
return syntax
? resolveDataTypes(
dictionary,
data ? typing(compatSyntax(data, parse(syntax))) : typing(parse(syntax)),
minTypesInDataTypes,
resolver,
)
: [{ type: Type.String }];
};

return resolver;
}

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

// Rename in case of conflict
if (realName in dictionary) {
const existingDataType = dictionary[realName];

for (const type of types) {
if (!hasType(existingDataType, type)) {
return addDataType(dictionary, name, types, index + 1);
}
}
for (const type of existingDataType) {
if (!hasType(types, type)) {
return addDataType(dictionary, name, types, index + 1);
}
}
}

dictionary[realName] = types;

return {
type: Type.DataType,
name: realName,
};
}
Loading