@polymer/gen-typescript-declarations
Advanced tools
Comparing version 1.0.0 to 1.0.1
@@ -9,2 +9,8 @@ # Changelog | ||
## [1.0.1] - 2018-02-01 | ||
- Always parameterize `Promise`. In Closure `Promise` is valid, but in TypeScript this is invalid and must be `Promise<any>` instead. | ||
- Escape `*\` comment end sequences when formatting comments. These turn up in practice when an HTML comment embeds a JavaScript style block comment, like here: https://github.com/PolymerElements/paper-icon-button/blob/master/paper-icon-button.html#L51 | ||
- Hybrid Polymer elements without a LHS assignment now have `Element` appended to their generated interface name, to match the behavior of the Closure Polymer Pass (https://github.com/google/closure-compiler/wiki/Polymer-Pass#element-type-names-for-1xhybrid-call-syntax). For example, `interface IronRequest` is now `interface IronRequestElement`. | ||
- Typings are now emitted for all HTML files, even if they contain no script tags. Added `index.html` to the default `exclude` set (alongside the existing `test/**` and `demo/**` globs). | ||
## [1.0.0] - 2018-01-25 | ||
@@ -11,0 +17,0 @@ - [BREAKING] The `--outDir` flag is now required when using the command line tool. Previously it would print all concatenated typings to `stdout`, which doesn't make much sense given that we emit multiple files. |
@@ -135,2 +135,7 @@ "use strict"; | ||
} | ||
else if (isBarePromise(node)) { | ||
// In Closure, `Promise` is ok, but in TypeScript this is invalid and must | ||
// be explicitly parameterized as `Promise<any>`. | ||
t = new ts.ParameterizedType('Promise', [ts.anyType]); | ||
} | ||
else if (isParameterizedType(node)) { | ||
@@ -233,4 +238,3 @@ t = convertParameterizedType(node, templateTypes); | ||
const name = renameMap.get(node.expression.name) || | ||
parameterizedRenameMap.get(node.expression.name) || | ||
node.expression.name; | ||
parameterizedRenameMap.get(node.expression.name) || node.expression.name; | ||
return new ts.ParameterizedType(name, types); | ||
@@ -297,2 +301,5 @@ } | ||
} | ||
function isBarePromise(node) { | ||
return node.type === 'NameExpression' && node.name === 'Promise'; | ||
} | ||
/** | ||
@@ -299,0 +306,0 @@ * Matches `Object<foo, bar>` but not `Object` (which is a NameExpression). |
@@ -7,3 +7,4 @@ /** | ||
* Skip source files whose paths match any of these glob patterns. If | ||
* undefined, defaults to excluding directories ending in "test" or "demo". | ||
* undefined, defaults to excluding "index.html" and directories ending in | ||
* "test" or "demo". | ||
*/ | ||
@@ -10,0 +11,0 @@ exclude?: string[]; |
@@ -27,2 +27,7 @@ "use strict"; | ||
const ts = require("./ts-ast"); | ||
const defaultExclude = [ | ||
'index.html', | ||
'test/**', | ||
'demo/**', | ||
]; | ||
/** | ||
@@ -49,15 +54,23 @@ * Analyze all files in the given directory using Polymer Analyzer, and return | ||
function analyzerToAst(analysis, config, rootDir) { | ||
const exclude = (config.exclude || ['test/**', 'demo/**']) | ||
.map((p) => new minimatch.Minimatch(p)); | ||
const exclude = (config.exclude || defaultExclude).map((p) => new minimatch.Minimatch(p)); | ||
const addReferences = config.addReferences || {}; | ||
const removeReferencesResolved = new Set((config.removeReferences || []).map((r) => path.resolve(rootDir, r))); | ||
const renameTypes = new Map(Object.entries(config.renameTypes || {})); | ||
// Analyzer can produce multiple JS documents with the same URL (e.g. an | ||
// HTML file with multiple inline scripts). We also might have multiple | ||
// files with the same basename (e.g. `foo.html` with an inline script, | ||
// and `foo.js`). We want to produce one declarations file for each | ||
// basename, so we first group Analyzer documents by their declarations | ||
// filename. | ||
const analyzerDocs = [ | ||
...analysis.getFeatures({ kind: 'html-document' }), | ||
...analysis.getFeatures({ kind: 'js-document' }), | ||
]; | ||
// We want to produce one declarations file for each file basename. There | ||
// might be both `foo.html` and `foo.js`, and we want their declarations to be | ||
// combined into a signal `foo.d.ts`. So we first group Analyzer documents by | ||
// their declarations filename. | ||
const declarationDocs = new Map(); | ||
for (const jsDoc of analysis.getFeatures({ kind: 'js-document' })) { | ||
for (const jsDoc of analyzerDocs) { | ||
// For every HTML or JS file, Analyzer is going to give us 1) the top-level | ||
// document, and 2) N inline documents for any nested content (e.g. script | ||
// tags in HTML). The top-level document will give us all the nested | ||
// features we need, so skip any inline ones. | ||
if (jsDoc.isInline) { | ||
continue; | ||
} | ||
const sourcePath = analyzerUrlToRelativePath(jsDoc.url, rootDir); | ||
@@ -204,6 +217,12 @@ if (sourcePath === undefined) { | ||
else if (feature.tagName) { | ||
// No `className` means this is an element defined by a call to the Polymer | ||
// function without a LHS assignment. We'll follow the convention of the | ||
// Closure Polymer Pass, and emit a global namespace interface called | ||
// `FooBarElement` (given a `tagName` of `foo-bar`). More context here: | ||
// | ||
// https://github.com/google/closure-compiler/wiki/Polymer-Pass#element-type-names-for-1xhybrid-call-syntax | ||
// https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/PolymerClassDefinition.java#L128 | ||
constructable = false; | ||
shortName = kebabToCamel(feature.tagName); | ||
shortName = kebabToCamel(feature.tagName) + 'Element'; | ||
fullName = shortName; | ||
// We're going to pollute the global scope with an interface. | ||
parent = root; | ||
@@ -210,0 +229,0 @@ } |
@@ -581,6 +581,16 @@ "use strict"; | ||
function formatComment(comment, depth) { | ||
// Make sure we don't end our comment early by printing out the `*/` end | ||
// comment sequence if it is contained in the comment. Escape it as `*\/` | ||
// instead. One way this sequence could get here is if an HTML comment | ||
// embedded a JavaScript style block comment. | ||
comment = comment.replace(/\*\//g, '*\\/'); | ||
// Indent the comment one space so that it doesn't touch the `*` we add next, | ||
// but only if there is a character there. If we also indented blank lines by | ||
// one space, then they would have an unneccessary space after the `*`. | ||
comment = comment.replace(/^(.)/gm, ' $1'); | ||
// Indent to the given level and add the `*` character. | ||
const i = indent(depth); | ||
return `${i}/**\n` + | ||
comment.replace(/^(.)/gm, ' $1').replace(/^/gm, `${i} *`) + `\n${i} */\n`; | ||
comment = comment.replace(/^/gm, `${i} *`); | ||
return `${i}/**\n${comment}\n${i} */\n`; | ||
} | ||
//# sourceMappingURL=ts-ast.js.map |
{ | ||
"name": "@polymer/gen-typescript-declarations", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "Generate TypeScript type declarations for Polymer components.", | ||
@@ -16,10 +16,10 @@ "main": "lib/gen-ts.js", | ||
"@types/doctrine": "0.0.3", | ||
"@types/fs-extra": "^4.0.2", | ||
"command-line-args": "^4.0.7", | ||
"@types/fs-extra": "^5.0.0", | ||
"command-line-args": "^5.0.1", | ||
"command-line-usage": "^4.0.1", | ||
"doctrine": "^2.0.0", | ||
"escodegen": "^1.9.0", | ||
"fs-extra": "^4.0.2", | ||
"fs-extra": "^5.0.0", | ||
"minimatch": "^3.0.4", | ||
"polymer-analyzer": "=3.0.0-pre.7" | ||
"polymer-analyzer": "=3.0.0-pre.9" | ||
}, | ||
@@ -34,6 +34,6 @@ "devDependencies": { | ||
"glob": "^7.1.2", | ||
"mocha": "^3.5.3", | ||
"mocha": "^5.0.0", | ||
"source-map-support": "^0.5.0", | ||
"tsc-then": "^1.0.1", | ||
"typescript": "^2.5.3" | ||
"typescript": "~2.6.2" | ||
}, | ||
@@ -40,0 +40,0 @@ "scripts": { |
# gen-typescript-declarations | ||
[![Build Status](https://travis-ci.org/PolymerLabs/gen-typescript-declarations.svg?branch=master)](https://travis-ci.org/PolymerLabs/gen-typescript-declarations) | ||
[![Build Status](https://travis-ci.org/Polymer/gen-typescript-declarations.svg?branch=master)](https://travis-ci.org/Polymer/gen-typescript-declarations) | ||
[![NPM version](https://img.shields.io/npm/v/@polymer/gen-typescript-declarations.svg)](https://www.npmjs.com/package/@polymer/gen-typescript-declarations) | ||
@@ -5,0 +5,0 @@ |
@@ -149,3 +149,7 @@ /** | ||
t = convertIndexableObject(node, templateTypes); | ||
} else if (isParameterizedType(node)) { // Type<T> | ||
} else if (isBarePromise(node)) { // Promise | ||
// In Closure, `Promise` is ok, but in TypeScript this is invalid and must | ||
// be explicitly parameterized as `Promise<any>`. | ||
t = new ts.ParameterizedType('Promise', [ts.anyType]); | ||
} else if (isParameterizedType(node)) { // foo<T> | ||
t = convertParameterizedType(node, templateTypes); | ||
@@ -250,7 +254,6 @@ } else if (isUnion(node)) { // foo|bar | ||
} | ||
const types = node.applications.map((application) => | ||
convert(application, templateTypes)); | ||
const types = node.applications.map( | ||
(application) => convert(application, templateTypes)); | ||
const name = renameMap.get(node.expression.name) || | ||
parameterizedRenameMap.get(node.expression.name) || | ||
node.expression.name; | ||
parameterizedRenameMap.get(node.expression.name) || node.expression.name; | ||
return new ts.ParameterizedType(name, types); | ||
@@ -336,6 +339,11 @@ } | ||
function isBareArray(node: doctrine.Type): | ||
node is doctrine.type.TypeApplication { | ||
node is doctrine.type.NameExpression { | ||
return node.type === 'NameExpression' && node.name === 'Array'; | ||
} | ||
function isBarePromise(node: doctrine.Type): | ||
node is doctrine.type.NameExpression { | ||
return node.type === 'NameExpression' && node.name === 'Promise'; | ||
} | ||
/** | ||
@@ -342,0 +350,0 @@ * Matches `Object<foo, bar>` but not `Object` (which is a NameExpression). |
@@ -27,3 +27,4 @@ /** | ||
* Skip source files whose paths match any of these glob patterns. If | ||
* undefined, defaults to excluding directories ending in "test" or "demo". | ||
* undefined, defaults to excluding "index.html" and directories ending in | ||
* "test" or "demo". | ||
*/ | ||
@@ -54,2 +55,8 @@ exclude?: string[]; | ||
const defaultExclude = [ | ||
'index.html', | ||
'test/**', | ||
'demo/**', | ||
]; | ||
/** | ||
@@ -77,4 +84,4 @@ * Analyze all files in the given directory using Polymer Analyzer, and return | ||
ts.Document[] { | ||
const exclude = (config.exclude || ['test/**', 'demo/**']) | ||
.map((p) => new minimatch.Minimatch(p)); | ||
const exclude = | ||
(config.exclude || defaultExclude).map((p) => new minimatch.Minimatch(p)); | ||
const addReferences = config.addReferences || {}; | ||
@@ -85,10 +92,20 @@ const removeReferencesResolved = new Set( | ||
// Analyzer can produce multiple JS documents with the same URL (e.g. an | ||
// HTML file with multiple inline scripts). We also might have multiple | ||
// files with the same basename (e.g. `foo.html` with an inline script, | ||
// and `foo.js`). We want to produce one declarations file for each | ||
// basename, so we first group Analyzer documents by their declarations | ||
// filename. | ||
const analyzerDocs = [ | ||
...analysis.getFeatures({kind: 'html-document'}), | ||
...analysis.getFeatures({kind: 'js-document'}), | ||
]; | ||
// We want to produce one declarations file for each file basename. There | ||
// might be both `foo.html` and `foo.js`, and we want their declarations to be | ||
// combined into a signal `foo.d.ts`. So we first group Analyzer documents by | ||
// their declarations filename. | ||
const declarationDocs = new Map<string, analyzer.Document[]>(); | ||
for (const jsDoc of analysis.getFeatures({kind: 'js-document'})) { | ||
for (const jsDoc of analyzerDocs) { | ||
// For every HTML or JS file, Analyzer is going to give us 1) the top-level | ||
// document, and 2) N inline documents for any nested content (e.g. script | ||
// tags in HTML). The top-level document will give us all the nested | ||
// features we need, so skip any inline ones. | ||
if (jsDoc.isInline) { | ||
continue; | ||
} | ||
const sourcePath = analyzerUrlToRelativePath(jsDoc.url, rootDir); | ||
@@ -245,6 +262,12 @@ if (sourcePath === undefined) { | ||
} else if (feature.tagName) { | ||
// No `className` means this is an element defined by a call to the Polymer | ||
// function without a LHS assignment. We'll follow the convention of the | ||
// Closure Polymer Pass, and emit a global namespace interface called | ||
// `FooBarElement` (given a `tagName` of `foo-bar`). More context here: | ||
// | ||
// https://github.com/google/closure-compiler/wiki/Polymer-Pass#element-type-names-for-1xhybrid-call-syntax | ||
// https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/PolymerClassDefinition.java#L128 | ||
constructable = false; | ||
shortName = kebabToCamel(feature.tagName); | ||
shortName = kebabToCamel(feature.tagName) + 'Element'; | ||
fullName = shortName; | ||
// We're going to pollute the global scope with an interface. | ||
parent = root; | ||
@@ -251,0 +274,0 @@ |
@@ -738,5 +738,18 @@ /** | ||
function formatComment(comment: string, depth: number): string { | ||
// Make sure we don't end our comment early by printing out the `*/` end | ||
// comment sequence if it is contained in the comment. Escape it as `*\/` | ||
// instead. One way this sequence could get here is if an HTML comment | ||
// embedded a JavaScript style block comment. | ||
comment = comment.replace(/\*\//g, '*\\/') | ||
// Indent the comment one space so that it doesn't touch the `*` we add next, | ||
// but only if there is a character there. If we also indented blank lines by | ||
// one space, then they would have an unneccessary space after the `*`. | ||
comment = comment.replace(/^(.)/gm, ' $1') | ||
// Indent to the given level and add the `*` character. | ||
const i = indent(depth); | ||
return `${i}/**\n` + | ||
comment.replace(/^(.)/gm, ' $1').replace(/^/gm, `${i} *`) + `\n${i} */\n`; | ||
comment = comment.replace(/^/gm, `${i} *`); | ||
return `${i}/**\n${comment}\n${i} */\n`; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
182741
3658
+ Added@types/fs-extra@5.1.0(transitive)
+ Addedcommand-line-args@5.2.1(transitive)
+ Addedfind-replace@3.0.0(transitive)
+ Addedfs-extra@5.0.0(transitive)
+ Addedlodash.camelcase@4.3.0(transitive)
+ Addedtypical@4.0.0(transitive)
- Removed@types/fs-extra@4.0.15(transitive)
- Removedarray-back@1.0.4(transitive)
- Removedcommand-line-args@4.0.7(transitive)
- Removedfind-replace@1.0.3(transitive)
- Removedfs-extra@4.0.3(transitive)
- Removedtest-value@2.1.0(transitive)
Updated@types/fs-extra@^5.0.0
Updatedcommand-line-args@^5.0.1
Updatedfs-extra@^5.0.0