diff --git a/packages/types-publisher/definition-parser.ts b/packages/types-publisher/definition-parser.ts index c0ceea83..0b61ffd3 100644 --- a/packages/types-publisher/definition-parser.ts +++ b/packages/types-publisher/definition-parser.ts @@ -18,7 +18,9 @@ export enum DefinitionFileKind { // More than one 'declare module "foo"'' MultipleModules, // Augments an external module - ModuleAugmentation + ModuleAugmentation, + // Old-style UMD + OldUMD } export enum RejectionReason { @@ -46,7 +48,7 @@ export function isFail(t: TypingParseSucceedResult | TypingParseFailResult): t i } export interface TypingsData { - type: string; + kind: string; moduleDependencies: string[]; libraryDependencies: string[]; @@ -54,26 +56,22 @@ export interface TypingsData { // e.g. https://github.com/DefinitelyTyped sourceRepoURL: string; - // The name of the primary definition file + // The name of the primary definition file, e.g. 'jquery.d.ts' definitionFilename: string; // The name of the library (human readable, e.g. might be 'Moment.js' even though packageName is 'moment') libraryName: string; - // True if the 'packageName' corresponds to the NPM package of the same name - hasNpmPackage: boolean; - - // The NPM name to publish this under + // The NPM name to publish this under, e.g. 'jquery'. May not be lower-cased yet. packageName: string; + // Parsed from 'Definitions by:' authors: string; - // Parent folder name in the source repo - folder: string; - // Optionally-presesnt name or URL of the project + // Optionally-present name or URL of the project, e.g. 'http://cordova.apache.org' projectName: string; - // Names introduced into the global scope + // Names introduced into the global scope by this definition set globals: string[]; // The major version of the library (e.g. '1' for 1.0, '2' for 2.0) @@ -81,21 +79,26 @@ export interface TypingsData { // The minor version of the library libraryMinorVersion: string; - // Files that should be published with this definition + // The full path to the containing folder of all files, e.g. 'C:/github/DefinitelyTyped' + root: string; + + // Files that should be published with this definition, e.g. ['jquery.d.ts', 'jquery-extras.d.ts'] files: string[]; } +const augmentedGlobals = ['Array',' Function', 'String', 'Number', 'Window', 'Date', 'StringConstructor', 'NumberConstructor', 'Math', 'HTMLElement']; + function isSupportedFileKind(kind: DefinitionFileKind) { switch(kind) { case DefinitionFileKind.Unknown: case DefinitionFileKind.MultipleModules: case DefinitionFileKind.Mixed: case DefinitionFileKind.DeclareModule: - return false; case DefinitionFileKind.Global: case DefinitionFileKind.ProperModule: case DefinitionFileKind.ModuleAugmentation: case DefinitionFileKind.UMD: + case DefinitionFileKind.OldUMD: return true; default: throw new Error('Should not be here'); @@ -111,6 +114,7 @@ enum DeclarationFlags { Value = 1 << 0, Type = 1 << 1, Namespace = 1 << 2, + Augmentation = 1 << 3 } function getNamespaceFlags(ns: ts.ModuleDeclaration): DeclarationFlags { @@ -161,20 +165,29 @@ export function getTypingInfo(directory: string): TypingParseFailResult | Typing log.push(`Found ${files.length} files`); const declFiles = files.filter(f => /\.d\.ts$/.test(f)); + const candidates = [path.basename(directory) + ".d.ts", "index.d.ts"]; log.push(`Found ${declFiles.length} .d.ts files (${declFiles.join(', ')})`); - if (declFiles.length !== 1) { - log.push('Exiting, can only process directories with exactly 1 .d.ts file'); - return { log, rejectionReason: RejectionReason.TooManyFiles }; + let entryPointFilename: string; + if (declFiles.length === 1) { + entryPointFilename = declFiles[0]; + } + else if(declFiles.length > 1) { + // You can have [foldername].d.ts, or index.d.ts to rescue yourself from this situation + for(const candidate of candidates) { + if(declFiles.indexOf(candidate) >= 0) { + log.push(`Used ${candidate} as entry point`); + entryPointFilename = candidate; + break; + } + } } - const declFilename = declFiles[0]; - log.push(`Parse ${declFilename}`); - const fullPath = path.join(directory, declFilename); - - let content = fs.readFileSync(fullPath, 'utf-8'); - if (content.charCodeAt(0) === 0xFEFF) content = content.substr(1); - const src = ts.createSourceFile('test.d.ts', content, ts.ScriptTarget.Latest, true); + if (entryPointFilename === undefined) { + log.push('Exiting, found either zero or more than one .d.ts file and none of ' + candidates.join(' or ')); + return { log, rejectionReason: RejectionReason.TooManyFiles }; + } + const entryPointContent = readFile(entryPointFilename); let hasUmdDecl = false; let isProperModule = false; @@ -182,101 +195,134 @@ export function getTypingInfo(directory: string): TypingParseFailResult | Typing let ambientModuleCount = 0; const moduleDependencies: string[] = []; + const referencedLibraries: string[] = []; let globalSymbols: { [name: string]: ts.SymbolFlags } = {}; function recordSymbol(name: string, flags: DeclarationFlags) { globalSymbols[name] = (globalSymbols[name] || DeclarationFlags.None) | flags; } - src.getChildren()[0].getChildren().forEach(node => { - switch(node.kind) { - case ts.SyntaxKind.GlobalModuleExportDeclaration: - const globalName = (node as ts.GlobalModuleExportDeclaration).name.getText(); - log.push(`Found UMD module declaration for global ${globalName}`); - // Don't set hasGlobalDeclarations = true even though we add a symbol here - // since this is still a legal module-only declaration - globalSymbols[globalName] = ts.SymbolFlags.Value; - isProperModule = true; - hasUmdDecl = true; - break; + const processQueue = [entryPointFilename]; + const completeList: string[] = []; - case ts.SyntaxKind.ModuleDeclaration: - if (node.flags & ts.NodeFlags.Export) { - log.push(`Found exported namespace "${(node as ts.ModuleDeclaration).name.getText()}"`); - isProperModule = true; - } else { - const nameKind = (node as ts.ModuleDeclaration).name.kind; - if (nameKind === ts.SyntaxKind.StringLiteral) { - log.push(`Found ambient external module ${(node as ts.ModuleDeclaration).name.getText()}`); - ambientModuleCount++; - } else { - const moduleName = (node as ts.ModuleDeclaration).name.getText(); - log.push(`Found global namespace declaration "${moduleName}"`); - hasGlobalDeclarations = true; - //console.log(node.getText()); - recordSymbol(moduleName, getNamespaceFlags(node as ts.ModuleDeclaration)); - } - } - break; - - case ts.SyntaxKind.VariableStatement: - if (node.flags & ts.NodeFlags.Export) { - log.push('Found exported variables'); - isProperModule = true; - } else { - (node as ts.VariableStatement).declarationList.declarations.forEach(decl => { - const declName = decl.name.getText(); - log.push(`Found global variable ${declName}`); - recordSymbol(declName, DeclarationFlags.Value); - }); - hasGlobalDeclarations = true; - } - break; - - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.FunctionDeclaration: - // If these nodes have an 'export' modifier, the file is an external module - if (node.flags & ts.NodeFlags.Export) { - log.push(`Found exported declaration "${(node as ts.Declaration).name.getText()}"`); - isProperModule = true; - } else { - const declName = (node as ts.Declaration).name.getText(); - const isType = node.kind === ts.SyntaxKind.InterfaceDeclaration || node.kind === ts.SyntaxKind.TypeAliasDeclaration; - log.push(`Found global ${isType ? 'type' : 'value'} declaration "${declName}"`); - recordSymbol(declName, isType ? DeclarationFlags.Type : DeclarationFlags.Value); - hasGlobalDeclarations = true; - } - break; - - case ts.SyntaxKind.ImportEqualsDeclaration: - if((node as ts.ImportEqualsDeclaration).moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) { - const ref = (node as ts.ImportEqualsDeclaration).moduleReference.getText(); - moduleDependencies.push(stripQuotes(ref)); - log.push(`Found import = declaration from ${ref}`); - isProperModule = true; - } - break; - - case ts.SyntaxKind.ImportDeclaration: - if((node as ts.ImportDeclaration).moduleSpecifier.kind === ts.SyntaxKind.StringLiteral) { - const ref = (node as ts.ImportDeclaration).moduleSpecifier.getText(); - moduleDependencies.push(stripQuotes(ref)); - log.push(`Found import declaration from ${ref}`); - isProperModule = true; - } - break; - - case ts.SyntaxKind.ExportDeclaration: - case ts.SyntaxKind.ExportAssignment: - // These nodes always indicate an external module - log.push(`Found export assignment or export declaration`); - isProperModule = true; - break; + while(processQueue.length > 0) { + const filename = processQueue.pop(); + if (completeList.indexOf(filename) >= 0) { + continue; } - }); + completeList.push(filename); + + log.push(`Parse ${filename}`); + let content = readFile(filename); + + const src = ts.createSourceFile('test.d.ts', content, ts.ScriptTarget.Latest, true); + src.referencedFiles.forEach(ref => { + // Add referenced files to processing queue + if(ref.fileName.charAt(0) !== '.') { + processQueue.push(path.join(path.dirname(filename), ref.fileName)); + } + }); + + // TODO: Remove type assertion + ((src).referencedLibraries || []).forEach((ref: {fileName: string}) => { + if(referencedLibraries.indexOf(ref.fileName) < 0) { + referencedLibraries.push(ref.fileName); + } + }); + + src.getChildren()[0].getChildren().forEach(node => { + switch(node.kind) { + case ts.SyntaxKind.GlobalModuleExportDeclaration: + const globalName = (node as ts.GlobalModuleExportDeclaration).name.getText(); + log.push(`Found UMD module declaration for global ${globalName}`); + // Don't set hasGlobalDeclarations = true even though we add a symbol here + // since this is still a legal module-only declaration + globalSymbols[globalName] = ts.SymbolFlags.Value; + isProperModule = true; + hasUmdDecl = true; + break; + + case ts.SyntaxKind.ModuleDeclaration: + if (node.flags & ts.NodeFlags.Export) { + log.push(`Found exported namespace "${(node as ts.ModuleDeclaration).name.getText()}"`); + isProperModule = true; + } else { + const nameKind = (node as ts.ModuleDeclaration).name.kind; + if (nameKind === ts.SyntaxKind.StringLiteral) { + log.push(`Found ambient external module ${(node as ts.ModuleDeclaration).name.getText()}`); + ambientModuleCount++; + } else { + const moduleName = (node as ts.ModuleDeclaration).name.getText(); + log.push(`Found global namespace declaration "${moduleName}"`); + hasGlobalDeclarations = true; + recordSymbol(moduleName, getNamespaceFlags(node as ts.ModuleDeclaration)); + } + } + break; + + case ts.SyntaxKind.VariableStatement: + if (node.flags & ts.NodeFlags.Export) { + log.push('Found exported variables'); + isProperModule = true; + } else { + (node as ts.VariableStatement).declarationList.declarations.forEach(decl => { + const declName = decl.name.getText(); + log.push(`Found global variable ${declName}`); + recordSymbol(declName, DeclarationFlags.Value); + }); + hasGlobalDeclarations = true; + } + break; + + case ts.SyntaxKind.InterfaceDeclaration: + case ts.SyntaxKind.TypeAliasDeclaration: + case ts.SyntaxKind.EnumDeclaration: + case ts.SyntaxKind.ClassDeclaration: + case ts.SyntaxKind.FunctionDeclaration: + // If these nodes have an 'export' modifier, the file is an external module + if (node.flags & ts.NodeFlags.Export) { + log.push(`Found exported declaration "${(node as ts.Declaration).name.getText()}"`); + isProperModule = true; + } else { + const declName = (node as ts.Declaration).name.getText(); + const isType = node.kind === ts.SyntaxKind.InterfaceDeclaration || node.kind === ts.SyntaxKind.TypeAliasDeclaration; + log.push(`Found global ${isType ? 'type' : 'value'} declaration "${declName}"`); + recordSymbol(declName, isType ? DeclarationFlags.Type : DeclarationFlags.Value); + hasGlobalDeclarations = true; + } + break; + + case ts.SyntaxKind.ImportEqualsDeclaration: + if((node as ts.ImportEqualsDeclaration).moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) { + const ref = (node as ts.ImportEqualsDeclaration).moduleReference.getText(); + moduleDependencies.push(stripQuotes(ref)); + log.push(`Found import = declaration from ${ref}`); + isProperModule = true; + } + break; + + case ts.SyntaxKind.ImportDeclaration: + if((node as ts.ImportDeclaration).moduleSpecifier.kind === ts.SyntaxKind.StringLiteral) { + const ref = (node as ts.ImportDeclaration).moduleSpecifier.getText(); + moduleDependencies.push(stripQuotes(ref)); + log.push(`Found import declaration from ${ref}`); + isProperModule = true; + } + break; + + case ts.SyntaxKind.ExportDeclaration: + case ts.SyntaxKind.ExportAssignment: + // These nodes always indicate an external module + log.push(`Found export assignment or export declaration`); + isProperModule = true; + break; + } + }); + } + + let hasGlobalAugmentations = false; + const globals = Object.keys(globalSymbols).filter(s => augmentedGlobals.indexOf(s) < 0); + const globalAugments = Object.keys(globalSymbols).filter(s => augmentedGlobals.indexOf(s) >= 0); let fileKind = DefinitionFileKind.Unknown; if (isProperModule) { @@ -295,8 +341,13 @@ export function getTypingInfo(directory: string): TypingParseFailResult | Typing } else { if (hasGlobalDeclarations) { if (ambientModuleCount == 1) { - log.push(`Global declarations and one ambient module declaration, this is a Mixed file`); - fileKind = DefinitionFileKind.Mixed; + if (globals.length === 1) { + log.push(`One global declaration and one ambient module declaration, this is an OldUMD file`); + fileKind = DefinitionFileKind.OldUMD; + } else { + log.push(`${globals.length} global declarations and one ambient module declaration, this is a Mixed file`); + fileKind = DefinitionFileKind.Mixed; + } } else if(ambientModuleCount > 1) { log.push(`Global declarations and multiple ambient module declaration, this is a MultipleModules file`); fileKind = DefinitionFileKind.MultipleModules; @@ -320,13 +371,8 @@ export function getTypingInfo(directory: string): TypingParseFailResult | Typing return { log, rejectionReason: RejectionReason.BadFileFormat }; } - if (src.referencedFiles.length > 0) { - log.push(`Exiting, typings files cannot have "/// " directives`); - return { log, rejectionReason: RejectionReason.ReferencePaths }; - } - function regexMatch(rx: RegExp, defaultValue: string): string { - const match = rx.exec(content); + const match = rx.exec(entryPointContent); return match ? match[1] : defaultValue; } @@ -335,27 +381,36 @@ export function getTypingInfo(directory: string): TypingParseFailResult | Typing const libraryMinorVersion = regexMatch(/^\/\/ Type definitions for \D+ v?\d+\.(\d+)/m, '0'); const libraryName = regexMatch(/^\/\/ Type definitions for ([A-Za-z]+)/m, 'Unknown').trim(); const projectName = regexMatch(/^\/\/ Project: (.+)$/m, ''); - const packageName = isProperModule ? path.basename(directory) : undefined; + const packageName = path.basename(directory); const sourceRepoURL = 'https://www.github.com/DefinitelyTyped/DefinitelyTyped'; + if(packageName !== packageName.toLowerCase()) { + log.push(`!!! WARNING: ${packageName} !== ${packageName.toLowerCase()}`); + } + return { log, data: { authors, - definitionFilename: declFilename, - libraryDependencies: src['referencedLibraries'], // TODO update + definitionFilename: entryPointFilename, + libraryDependencies: referencedLibraries, moduleDependencies, - folder: path.basename(directory), - hasNpmPackage: false, libraryMajorVersion, libraryMinorVersion, libraryName, packageName, projectName, sourceRepoURL, - type: DefinitionFileKind[fileKind], + kind: DefinitionFileKind[fileKind], globals: Object.keys(globalSymbols).filter(k => !!(globalSymbols[k] & DeclarationFlags.Value)), - files: [declFiles[0]] + root: path.resolve(directory), + files: declFiles } - } + }; + + function readFile(fileName: string) { + const result = fs.readFileSync(path.join(directory, fileName), 'utf-8'); + // Skip BOM + return (result.charCodeAt(0) === 0xFEFF) ? result.substr(1) : result; + } } diff --git a/packages/types-publisher/definition-publisher.ts b/packages/types-publisher/definition-publisher.ts index 77a61fd3..e4ac7e5b 100644 --- a/packages/types-publisher/definition-publisher.ts +++ b/packages/types-publisher/definition-publisher.ts @@ -2,6 +2,7 @@ import { TypingsData, DefinitionFileKind } from './definition-parser'; import * as fs from 'fs'; import * as crypto from 'crypto'; import * as path from 'path'; +import * as child_process from 'child_process'; export interface PublishSettings { // e.g. 'typings', not '@typings' @@ -20,7 +21,7 @@ namespace Versions { }; } - export function performUpdate(key: string, content: string, update: (version: number) => void) { + export function performUpdate(key: string, content: string, update: (version: number) => boolean) { let data: VersionMap = fs.existsSync(versionFilename) ? JSON.parse(fs.readFileSync(versionFilename, 'utf-8')) : {}; const hashValue = computeHash(key); @@ -30,12 +31,13 @@ namespace Versions { data[key] = entry = { lastVersion: 0, lastContentHash: '' }; } - if (entry.lastContentHash !== hashValue) { + if (entry.lastContentHash !== hashValue || process.argv.some(arg => arg === '--forceUpdate')) { const vNext = entry.lastVersion + 1; - update(vNext); - - data[key] = { lastVersion: vNext, lastContentHash: hashValue }; - fs.writeFileSync(versionFilename, JSON.stringify(data, undefined, 4)); + + if(update(vNext)) { + data[key] = { lastVersion: vNext, lastContentHash: hashValue }; + fs.writeFileSync(versionFilename, JSON.stringify(data, undefined, 4)); + } return true; } @@ -50,28 +52,72 @@ namespace Versions { } } -export function publish(typing: TypingsData, settings: PublishSettings): boolean { - const args: string[] = [ - 'publish', - // packagePath, - '--access public' - ]; +function mkdir(p: string) { + try { + fs.statSync(p); + } catch(e) { + fs.mkdirSync(p); + } +} - const content = fs.readFileSync(typing.definitionFilename, 'utf-8'); +function patchDefinitionFile(input: string): string { + const pathToLibrary = /\/\/\/ '); + return output; +} - return Versions.performUpdate(typing.folder, content, version => { - const packageJson = createPackageJSON(typing, settings, version); +export function publish(typing: TypingsData, settings: PublishSettings): { log: string[] } { + const log: string[] = []; + + log.push(`Possibly publishing ${typing.libraryName}`); + + let allContent = ''; + // Make the file ordering deterministic so the hash doesn't jump around for no reason + typing.files.sort(); + for(const file of typing.files) { + allContent = allContent + fs.readFileSync(path.join(typing.root, file), 'utf-8'); + } + + const actualPackageName = typing.packageName.toLowerCase(); + + const didUpdate = Versions.performUpdate(actualPackageName, allContent, version => { + log.push('Generate package.json and README.md; ensure output path exists'); + const packageJson = JSON.stringify(createPackageJSON(typing, settings, version), undefined, 4); const readme = createReadme(typing); - const outputPath = path.join(settings.outputPath, typing.folder); - if (!fs.exists(outputPath)) { - fs.mkdirSync(outputPath); - } + const outputPath = path.join(settings.outputPath, actualPackageName); + mkdir(outputPath); fs.writeFileSync(path.join(outputPath, 'package.json'), packageJson, 'utf-8'); fs.writeFileSync(path.join(outputPath, 'README.md'), readme, 'utf-8'); - fs.writeFileSync(path.join(outputPath, path.basename(typing.definitionFilename)), fs.readFileSync(typing.definitionFilename)); + + typing.files.forEach(file => { + log.push(`Copy and patch ${file}`); + let content = fs.readFileSync(path.join(typing.root, file), 'utf-8'); + content = patchDefinitionFile(file); + fs.writeFileSync(path.join(outputPath, file), file); + }); + + const args: string[] = ['npm', 'publish', path.resolve(outputPath), '--access public']; + const cmd = args.join(' '); + log.push(`Run ${cmd}`); + try { + const result = child_process.execSync(cmd, { encoding: 'utf-8' }); + log.push(`Ran successfully`); + log.push(result); + return true; + } catch(e) { + log.push(`!!! Publish failed`); + log.push(JSON.stringify(e)); + return false; + } }); + + if (!didUpdate) { + log.push('Package was already up-to-date'); + } + + return { log }; } @@ -81,7 +127,7 @@ function createPackageJSON(typing: TypingsData, settings: PublishSettings, fileV typing.libraryDependencies.forEach(d => dependencies[`@${settings.scopeName}/${d}`] = '*'); return ({ - name: `@${settings.scopeName}/${typing.packageName}`, + name: `@${settings.scopeName}/${typing.packageName.toLowerCase()}`, version: `${typing.libraryMajorVersion}.${typing.libraryMinorVersion}.${fileVersion}`, description: `Type definitions for ${typing.libraryName} from ${typing.sourceRepoURL}`, main: '', //? index.js', @@ -99,12 +145,7 @@ function createReadme(typing: TypingsData) { lines.push(`This package contains type definitions for ${typing.libraryName}.`) if (typing.projectName) { lines.push(''); - lines.push(`The project URL is ${typing.projectName}`); - } - - if (typing.hasNpmPackage) { - lines.push(''); - lines.push(`The corresponding NPM package is https://www.npmjs.com/package/${typing.packageName}`); + lines.push(`The project URL or description is ${typing.projectName}`); } if (typing.authors) { @@ -113,15 +154,16 @@ function createReadme(typing: TypingsData) { } lines.push(''); - lines.push(`Typings were exported from ${typing.sourceRepoURL} in the ${typing.folder} directory.`); + lines.push(`Typings were exported from ${typing.sourceRepoURL} in the ${typing.packageName} directory.`); lines.push(''); lines.push(`Additional Details`) lines.push(` * Last updated: ${(new Date()).toUTCString()}`); - lines.push(` * Typings kind: ${DefinitionFileKind[typing.type]}`); + lines.push(` * Typings kind: ${typing.kind}`); lines.push(` * Library Dependencies: ${typing.libraryDependencies.length ? typing.libraryDependencies.join(', ') : 'none'}`); lines.push(` * Module Dependencies: ${typing.moduleDependencies.length ? typing.moduleDependencies.join(', ') : 'none'}`); - lines.push(` * Globals: ${typing.globals.length ? typing.globals.join(', ') : 'none'}`); + lines.push(` * Global values: ${typing.globals.length ? typing.globals.join(', ') : 'none'}`); + lines.push(''); return lines.join('\r\n'); } diff --git a/packages/types-publisher/run.ts b/packages/types-publisher/run.ts index c79437f1..21083778 100644 --- a/packages/types-publisher/run.ts +++ b/packages/types-publisher/run.ts @@ -1,6 +1,7 @@ /// import * as parser from './definition-parser'; +import * as publisher from './definition-publisher'; import fs = require('fs'); import path = require('path'); @@ -14,29 +15,39 @@ const OutputPath = './output/'; const summaryLog: string[] = []; const detailedLog: string[] = []; const outcomes: { [s: string]: number } = {}; +const kinds: { [s: string]: number } = {}; + +const publishSettings: publisher.PublishSettings = { outputPath: './output', scopeName: 'ryancavanaugh' }; + +function recordKind(s: string) { + kinds[s] = (kinds[s] || 0) + 1; +} function recordOutcome(s: string) { outcomes[s] = (outcomes[s] || 0) + 1; } -interface VersionMap { - [typingsPackageName: string]: string; -} - function processDir(folderPath: string, name: string) { detailedLog.push(`## ${name}`); const info = parser.getTypingInfo(folderPath); if (parser.isSuccess(info)) { - detailedLog.push('### Succeeded'); - detailedLog.push(`Detected a ${parser.DefinitionFileKind[info.data.type]} typing definition.`); + detailedLog.push('### File Parse Succeeded'); + detailedLog.push(`Detected a ${info.data.kind} typing definition.`); detailedLog.push('```js'); detailedLog.push(JSON.stringify(info.data, undefined, 4)); detailedLog.push('```'); - recordOutcome(`Succeeded (${parser.DefinitionFileKind[info.data.type]})`); + recordOutcome(`Succeeded (${info.data.kind})`); + recordKind(info.data.kind); + + detailedLog.push('### Publish'); + const publishLog = publisher.publish(info.data, publishSettings); + for(const line of publishLog.log) { + detailedLog.push(` > ${line}\r\n\r\n`); + } } else if(parser.isFail(info)) { - detailedLog.push('### Failed'); + detailedLog.push('### File Parse Failed'); switch (info.rejectionReason) { case parser.RejectionReason.BadFileFormat: recordOutcome('Failed: Bad file format'); @@ -56,7 +67,7 @@ function processDir(folderPath: string, name: string) { } detailedLog.push('### Parser Log'); - for(const line of info.log) detailedLog.push('> ' + line); + for(const line of info.log) detailedLog.push('> ' + line + '\r\n'); detailedLog.push(''); } @@ -76,11 +87,20 @@ function main() { folders.forEach(s => processDir(s.path, s.name)); - summaryLog.push('\r\n### Overall Results'); + summaryLog.push('\r\n### Overall Results\r\n'); + + summaryLog.push(' * Pass / fail'); const outcomeKeys = Object.keys(outcomes); outcomeKeys.sort(); outcomeKeys.forEach(k => { - summaryLog.push(` * ${k}: ${outcomes[k]}`); + summaryLog.push(` * ${k}: ${outcomes[k]}`); + }); + + summaryLog.push(' * Typing Kind'); + const typingKeys = Object.keys(kinds); + typingKeys.sort(); + typingKeys.forEach(k => { + summaryLog.push(` * ${k}: ${kinds[k]}`); }); const logmd = summaryLog.join('\r\n') + '\r\n\r\n# Detailed Report\r\n\r\n' + detailedLog.join('\r\n'); diff --git a/packages/types-publisher/tsconfig.json b/packages/types-publisher/tsconfig.json index ded12d90..02b29f43 100644 --- a/packages/types-publisher/tsconfig.json +++ b/packages/types-publisher/tsconfig.json @@ -6,6 +6,7 @@ "typings/tsd.d.ts" ], "compilerOptions": { - "module": "commonjs" + "module": "commonjs", + "noImplicitAny": true } } \ No newline at end of file