diff --git a/packages/analyzer/CHANGELOG.md b/packages/analyzer/CHANGELOG.md index 9e093bc58..c1a992c88 100644 --- a/packages/analyzer/CHANGELOG.md +++ b/packages/analyzer/CHANGELOG.md @@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). - +## Unreleased +* Typings change: `ParsedDocument#astNode` had the type `any`. It now has a + more strict type of `{} | null | undefined`. If this breaks downstream code, + that code should probably use a more specific type of `ParsedDocument`, or + `Document`. ## [3.0.0-pre.23] - 2018-04-17 diff --git a/packages/analyzer/src/core/analyzer.ts b/packages/analyzer/src/core/analyzer.ts index 412c3ed4b..2360df14b 100644 --- a/packages/analyzer/src/core/analyzer.ts +++ b/packages/analyzer/src/core/analyzer.ts @@ -66,7 +66,8 @@ export interface ForkOptions { urlLoader?: UrlLoader; } export class NoKnownParserError extends Error {}; -export type ScannerTable = Map[]>; +export type ScannerTable = + Map[]>; export type LazyEdgeMap = Map; /** diff --git a/packages/analyzer/src/html/html-document.ts b/packages/analyzer/src/html/html-document.ts index ce29ebf47..9f779f4bc 100644 --- a/packages/analyzer/src/html/html-document.ts +++ b/packages/analyzer/src/html/html-document.ts @@ -179,7 +179,7 @@ export class ParsedHtmlDocument extends ParsedDocument { // We can modify these, as they don't escape this method. const mutableDocuments = clone(immutableDocuments); - const selfClone = mutableDocuments.shift()!; + const selfClone: this = mutableDocuments.shift()! as this; // We must handle documents that are inline to us but mutated here. // If they're not inline us, we'll pass them along to our child documents diff --git a/packages/analyzer/src/parser/document.ts b/packages/analyzer/src/parser/document.ts index 8ccc4b5ab..c93dfc22f 100644 --- a/packages/analyzer/src/parser/document.ts +++ b/packages/analyzer/src/parser/document.ts @@ -22,7 +22,9 @@ import {ResolvedUrl} from '../model/url'; * @template AstNode The AST type of the document. * @template Visitor The type of the visitors that can walk the document. */ -export abstract class ParsedDocument { +export abstract class ParsedDocument< + AstNode = {} | null | undefined, + Visitor = {}> { abstract type: string; url: ResolvedUrl; baseUrl: ResolvedUrl; diff --git a/packages/analyzer/src/test/core/analyzer_test.ts b/packages/analyzer/src/test/core/analyzer_test.ts index 5d8b0bba8..a13d287eb 100644 --- a/packages/analyzer/src/test/core/analyzer_test.ts +++ b/packages/analyzer/src/test/core/analyzer_test.ts @@ -655,10 +655,10 @@ suite('Analyzer', () => { const document = new HtmlParser().parse( contents, resolvedUrl`test.html`, new PackageUrlResolver()); const context = await getContext(analyzer); - const features = - (await context['_getScannedFeatures'](document)) - .features.filter((e) => e instanceof ScannedImport) as - ScannedImport[]; + const features = (await context['_getScannedFeatures'](document)) + .features.filter( + (e: ScannedFeature) => e instanceof + ScannedImport) as ScannedImport[]; assert.equal(features.length, 1); assert.equal(features[0].type, 'css-import'); assert.equal(features[0].url, 'bar.css' as FileRelativeUrl); diff --git a/packages/bundler/.vscode/tasks.json b/packages/bundler/.vscode/tasks.json new file mode 100644 index 000000000..8a26d7ce2 --- /dev/null +++ b/packages/bundler/.vscode/tasks.json @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "test:watch", + "isBackground": true, + "presentation": { + "echo": false, + "reveal": "always", + "focus": false, + "panel": "dedicated" + }, + "group": { + "kind": "test", + "isDefault": true + }, + "promptOnClose": false, + "problemMatcher": { + "fileLocation": [ + "relative", + "${workspaceRoot}/src" + ], + "background": { + "beginsPattern": "tsc-then: Running", + "endsPattern": "tsc-then: command finished" + }, + "pattern": [ + { + "regexp": "^ (\\d+)\\) ((\\w+).*)", + "message": 2, + "file": 3, + "line": 1, + "column": 1 + } + ], + "applyTo": "allDocuments", + "severity": "error" + } + } + ] +} diff --git a/packages/bundler/CHANGELOG.md b/packages/bundler/CHANGELOG.md index f19448167..e42f91b14 100644 --- a/packages/bundler/CHANGELOG.md +++ b/packages/bundler/CHANGELOG.md @@ -5,7 +5,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). - +## Unreleased +- Bundled documents now have a `language` field. It will be `html` when the ast + node is an HTML Parse5 node, and `js` when the ast node is a JS babel node. ## 4.0.0-pre.5 - 2018-04-17 diff --git a/packages/bundler/package-lock.json b/packages/bundler/package-lock.json index aaed4f6b6..bc19ad654 100644 --- a/packages/bundler/package-lock.json +++ b/packages/bundler/package-lock.json @@ -2199,6 +2199,27 @@ "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" }, + "tsc-then": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tsc-then/-/tsc-then-1.1.0.tgz", + "integrity": "sha512-830G8SK8tewOxfKVBC5YWqZ2C7wS1D4dh9267ebLxR7Gvh3UuI6aKU5Hxo+L3Kkcy6CuxZp4PMGl066DZ3Hlmw==", + "requires": { + "@types/node": "8.10.8", + "semver": "5.5.0" + }, + "dependencies": { + "@types/node": { + "version": "8.10.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.8.tgz", + "integrity": "sha512-BvcUxNZe9JgiiUVivtiQt3NrPVu9OAQzkxR1Ko9ESftCYU7V6Np5kpDzQwxd+34lsop7SNRdL292Flv52OvCaw==" + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + } + } + }, "tslint": { "version": "3.15.1", "resolved": "https://registry.npmjs.org/tslint/-/tslint-3.15.1.tgz", diff --git a/packages/bundler/package.json b/packages/bundler/package.json index 7bf5df0bb..b0d1b4678 100644 --- a/packages/bundler/package.json +++ b/packages/bundler/package.json @@ -48,6 +48,7 @@ "mocha": "^2.2.4", "rewire": "^2.5.2", "source-map-support": "^0.4.2", + "tsc-then": "^1.1.0", "tslint": "^3.15.1", "typescript": "^2.2.0", "typings": "^1.3.2" @@ -56,7 +57,8 @@ "build": "tsc", "format": "find src | grep '\\.js$\\|\\.ts$' | xargs ./node_modules/.bin/clang-format --style=file -i", "test": "npm run build && tslint -c tslint.json src/*.ts src/**/*.ts && mocha", - "test:unit": "mocha" + "test:unit": "mocha", + "test:watch": "tsc-then -- mocha" }, "author": "The Polymer Project Authors", "license": "BSD-3-Clause", diff --git a/packages/bundler/src/analyzer-utils.ts b/packages/bundler/src/analyzer-utils.ts index fbca7d027..d121512ed 100644 --- a/packages/bundler/src/analyzer-utils.ts +++ b/packages/bundler/src/analyzer-utils.ts @@ -11,7 +11,7 @@ * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ -import {Analysis, Document} from 'polymer-analyzer'; +import {Analysis, Document, ParsedHtmlDocument, ParsedJavaScriptDocument} from 'polymer-analyzer'; export function getAnalysisDocument(analysis: Analysis, url: string): Document { const result = analysis.getDocument(url); @@ -24,3 +24,23 @@ export function getAnalysisDocument(analysis: Analysis, url: string): Document { } throw new Error(`Unable to get document ${url}`); } + +export function assertIsHtmlDocument(doc: Document): + Document { + if (doc.kinds.has('html-document')) { + return doc as Document; + } else { + throw new Error( + `Document wasn't an HTML document, it's a: ${[...doc.kinds]}`); + } +} + +export function assertIsJsDocument(doc: Document): + Document { + if (doc.kinds.has('js-document')) { + return doc as Document; + } else { + throw new Error( + `Document wasn't an JS document, it's a: ${[...doc.kinds]}`); + } +} diff --git a/packages/bundler/src/bundler.ts b/packages/bundler/src/bundler.ts index f69922343..ca8287cd7 100644 --- a/packages/bundler/src/bundler.ts +++ b/packages/bundler/src/bundler.ts @@ -17,7 +17,7 @@ import {getAnalysisDocument} from './analyzer-utils'; import * as bundleManifestLib from './bundle-manifest'; import {Bundle, BundleManifest, BundleStrategy, BundleUrlMapper} from './bundle-manifest'; import * as depsIndexLib from './deps-index'; -import {BundledDocument, DocumentCollection} from './document-collection'; +import {DocumentCollection} from './document-collection'; import {bundle as bundleEs6Module} from './es6-module-bundler'; import {reserveBundleModuleExportNames} from './es6-module-utils'; import {bundle as bundleHtmlFragment} from './html-bundler'; @@ -109,8 +109,8 @@ export class Bundler { } /** - * Analyze a URL using the given contents in place of what would otherwise - * have been loaded. + * Analyze an HTML URL using the given contents in place of what would + * otherwise have been loaded. */ async analyzeContents( url: ResolvedUrl, @@ -145,8 +145,7 @@ export class Bundler { * @param manifest - The manifest that describes the bundles to be produced. */ async bundle(manifest: BundleManifest): Promise { - const documents: DocumentCollection = - new Map(); + const documents = new DocumentCollection(); manifest = manifest.fork(); // Ensure exports of modules sharing the URL of their bundle have priority diff --git a/packages/bundler/src/document-collection.ts b/packages/bundler/src/document-collection.ts index 964e24c9b..5ba56caa9 100644 --- a/packages/bundler/src/document-collection.ts +++ b/packages/bundler/src/document-collection.ts @@ -11,14 +11,48 @@ * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ +import * as babel from 'babel-types'; import {ASTNode} from 'parse5'; import {ResolvedUrl} from 'polymer-analyzer'; -export interface BundledDocument { - ast: ASTNode; +export interface BundledBaseDocument { + ast: Node; content: string; files: ResolvedUrl[]; } +export type BundledHtmlDocument = { + language: 'html' +} & BundledBaseDocument; +export type BundledJsDocument = { + language: 'js' +} & BundledBaseDocument; +export type BundledDocument = BundledHtmlDocument | BundledJsDocument; + + /* A collection of documents, keyed by path */ -export type DocumentCollection = Map; +export class DocumentCollection extends Map { + getHtmlDoc(url: ResolvedUrl) { + const result = this.get(url); + if (result === undefined) { + return undefined; + } + if (result.language !== 'html') { + throw new Error( + `Expected url ${url} to be html but it was ${result.language}`); + } + return result; + } + + getJsDoc(url: ResolvedUrl) { + const result = this.get(url); + if (result === undefined) { + return undefined; + } + if (result.language !== 'js') { + throw new Error( + `Expected url ${url} to be js but it was ${result.language}`); + } + return result; + } +} diff --git a/packages/bundler/src/es6-module-bundler.ts b/packages/bundler/src/es6-module-bundler.ts index 3d6d52215..12bf26de2 100644 --- a/packages/bundler/src/es6-module-bundler.ts +++ b/packages/bundler/src/es6-module-bundler.ts @@ -15,10 +15,10 @@ import generate from 'babel-generator'; import * as babel from 'babel-types'; import {ResolvedUrl} from 'polymer-analyzer'; -import {getAnalysisDocument} from './analyzer-utils'; +import {assertIsJsDocument, getAnalysisDocument} from './analyzer-utils'; import {AssignedBundle, BundleManifest} from './bundle-manifest'; import {Bundler} from './bundler'; -import {BundledDocument} from './document-collection'; +import {BundledJsDocument} from './document-collection'; import {getModuleExportNames, getOrSetBundleModuleExportName} from './es6-module-utils'; import {Es6Rewriter} from './es6-rewriter'; import {ensureLeadingDot, stripUrlFileSearchAndHash} from './url-utils'; @@ -28,7 +28,7 @@ import {ensureLeadingDot, stripUrlFileSearchAndHash} from './url-utils'; */ export async function bundle( bundler: Bundler, manifest: BundleManifest, url: ResolvedUrl): - Promise { + Promise { const bundle = manifest.bundles.get(url); if (!bundle) { throw new Error(`No bundle found in manifest for url ${url}.`); @@ -38,9 +38,10 @@ export async function bundle( await prepareBundleModule(bundler, manifest, assignedBundle); const es6Rewriter = new Es6Rewriter(bundler, manifest, assignedBundle); const {code: rolledUpCode} = await es6Rewriter.rollup(url, generatedCode); - const document = - await bundler.analyzeContents(assignedBundle.url, rolledUpCode); + const document = assertIsJsDocument( + await bundler.analyzeContents(assignedBundle.url, rolledUpCode)); return { + language: 'js', ast: document.parsedDocument.ast, content: document.parsedDocument.contents, files: [...assignedBundle.bundle.files] diff --git a/packages/bundler/src/es6-rewriter.ts b/packages/bundler/src/es6-rewriter.ts index 80c423439..d9c9e0804 100644 --- a/packages/bundler/src/es6-rewriter.ts +++ b/packages/bundler/src/es6-rewriter.ts @@ -17,7 +17,7 @@ import * as clone from 'clone'; import {FileRelativeUrl, PackageRelativeUrl, ResolvedUrl} from 'polymer-analyzer'; import {rollup} from 'rollup'; -import {getAnalysisDocument} from './analyzer-utils'; +import {assertIsJsDocument, getAnalysisDocument} from './analyzer-utils'; import {serialize} from './babel-utils'; import {AssignedBundle, BundleManifest} from './bundle-manifest'; import {Bundler} from './bundler'; @@ -124,7 +124,7 @@ export class Es6Rewriter { appendUrlPath(url, '_inline_es6_module.js'); const rolledUpDocument = await this.bundler.analyzeContents( rolledUpUrl as ResolvedUrl, rolledUpCode); - const babelFile = rolledUpDocument.parsedDocument.ast; + const babelFile = assertIsJsDocument(rolledUpDocument).parsedDocument.ast; this._rewriteImportStatements(url, babelFile); this._deduplicateImportStatements(babelFile); const {code: rewrittenCode} = serialize(babelFile); diff --git a/packages/bundler/src/html-bundler.ts b/packages/bundler/src/html-bundler.ts index 33bcee0a8..2a63dcf1b 100644 --- a/packages/bundler/src/html-bundler.ts +++ b/packages/bundler/src/html-bundler.ts @@ -17,11 +17,11 @@ import * as dom5 from 'dom5'; import {ASTNode, parseFragment, serialize, treeAdapters} from 'parse5'; import {Document, FileRelativeUrl, ParsedHtmlDocument, ResolvedUrl} from 'polymer-analyzer'; -import {getAnalysisDocument} from './analyzer-utils'; +import {assertIsHtmlDocument, getAnalysisDocument} from './analyzer-utils'; import {AssignedBundle, BundleManifest} from './bundle-manifest'; import {Bundler} from './bundler'; import constants from './constants'; -import {BundledDocument} from './document-collection'; +import {BundledHtmlDocument} from './document-collection'; import {Es6Rewriter} from './es6-rewriter'; import * as matchers from './matchers'; import {findAncestor, insertAfter, insertAllBefore, inSourceOrder, isSameNode, prepend, removeElementAndNewline, siblingsAfter, stripComments} from './parse5-utils'; @@ -36,7 +36,7 @@ import {find, rewriteObject} from './utils'; */ export async function bundle( bundler: Bundler, manifest: BundleManifest, url: ResolvedUrl): - Promise { + Promise { const bundle = manifest.bundles.get(url); if (!bundle) { throw new Error(`No bundle found in manifest for url ${url}.`); @@ -53,7 +53,7 @@ export async function bundle( * exported bundle function above. */ export class HtmlBundler { - protected document: Document; + protected document: Document; constructor( public bundler: Bundler, @@ -61,7 +61,7 @@ export class HtmlBundler { public manifest: BundleManifest) { } - async bundle(): Promise { + async bundle(): Promise { this.document = await this._prepareBundleDocument(); let ast = clone(this.document.parsedDocument.ast); dom5.removeFakeRootElements(ast); @@ -93,7 +93,7 @@ export class HtmlBundler { } const content = serialize(ast); const files = [...this.assignedBundle.bundle.files]; - return {ast, content, files}; + return {language: 'html', ast, content, files}; } /** @@ -728,13 +728,15 @@ export class HtmlBundler { * prepare it as the bundle document, otherwise we'll create a clean/empty * HTML document. */ - private async _prepareBundleDocument(): Promise { + private async _prepareBundleDocument(): + Promise> { if (!this.assignedBundle.bundle.files.has(this.assignedBundle.url)) { return this._reanalyze(''); } const analysis = await this.bundler.analyzer.analyze([this.assignedBundle.url]); - const document = getAnalysisDocument(analysis, this.assignedBundle.url); + const document = assertIsHtmlDocument( + getAnalysisDocument(analysis, this.assignedBundle.url)); const ast = clone(document.parsedDocument.ast); this._moveOrderedImperativesFromHeadIntoHiddenDiv(ast); this._moveUnhiddenHtmlImportsIntoHiddenDiv(ast); @@ -746,8 +748,10 @@ export class HtmlBundler { * Fetch a new copy of an analyzed document serializing an AST and analyzing * it. */ - private async _reanalyze(code: string): Promise { - return this.bundler.analyzeContents(this.assignedBundle.url, code); + private async _reanalyze(code: string): + Promise> { + return assertIsHtmlDocument( + await this.bundler.analyzeContents(this.assignedBundle.url, code)); } /** diff --git a/packages/bundler/src/test/bundler_test.ts b/packages/bundler/src/test/bundler_test.ts index 0e4195e93..da90a8afe 100644 --- a/packages/bundler/src/test/bundler_test.ts +++ b/packages/bundler/src/test/bundler_test.ts @@ -22,7 +22,6 @@ import {Analyzer, FsUrlLoader, FsUrlResolver} from 'polymer-analyzer'; import {Bundle, generateShellMergeStrategy} from '../bundle-manifest'; import {Bundler, Options as BundlerOptions} from '../bundler'; -import {BundledDocument} from '../document-collection'; import * as matchers from '../matchers'; import {resolvePath} from '../url-utils'; @@ -76,22 +75,21 @@ suite('Bundler', () => { const inputPath = 'default.html'; - async function bundle(inputPath: string, opts?: BundlerOptions): - Promise { - // Don't modify options directly because test-isolation problems occur. - bundler = getBundler(opts); - const resolvedInputPath = resolve(inputPath)!; - const manifest = await bundler.generateManifest([resolvedInputPath]); - const bundleResult = await bundler.bundle(manifest); - const bundleForFile = - bundleResult.manifest.getBundleForFile(resolvedInputPath); - if (!bundleForFile) { - throw new Error(`Unable to find bundle for ${resolvedInputPath}`); - } - documentBundle = bundleForFile.bundle; - const {documents} = bundleResult; - return documents.get(resolvedInputPath)!; - } + async function bundle(inputPath: string, opts?: BundlerOptions) { + // Don't modify options directly because test-isolation problems occur. + bundler = getBundler(opts); + const resolvedInputPath = resolve(inputPath)!; + const manifest = await bundler.generateManifest([resolvedInputPath]); + const bundleResult = await bundler.bundle(manifest); + const bundleForFile = + bundleResult.manifest.getBundleForFile(resolvedInputPath); + if (!bundleForFile) { + throw new Error(`Unable to find bundle for ${resolvedInputPath}`); + } + documentBundle = bundleForFile.bundle; + const {documents} = bundleResult; + return documents.getHtmlDoc(resolvedInputPath)!; + } suite('Default Options', () => { test('URLs for inlined HTML imports are recorded in Bundle', async () => { @@ -143,7 +141,7 @@ suite('Bundler', () => { const manifest = await bundler.generateManifest([resolve('default.html')]); const {documents} = await bundler.bundle(manifest); - const document = documents.get(resolve('default.html'))!; + const document = documents.getHtmlDoc(resolve('default.html'))!; assert(document); // Look for the script referenced in the external-script.html source. @@ -185,7 +183,7 @@ suite('Bundler', () => { const manifest = await bundler.generateManifest([resolve('default.html')]); const {documents} = await bundler.bundle(manifest); - const document = documents.get(resolve('default.html'))!; + const document = documents.getHtmlDoc(resolve('default.html'))!; assert(document); // We've moved the 'imports/simple-import.html' into a shared bundle @@ -199,7 +197,7 @@ suite('Bundler', () => { assert.equal( dom5.getAttribute(linkTag, 'href'), 'shared_bundle_1.html'); - const shared = documents.get(resolve('shared_bundle_1.html'))!; + const shared = documents.getHtmlDoc(resolve('shared_bundle_1.html'))!; assert(shared); assert.isOk(dom5.query( shared.ast, dom5.predicates.hasAttrValue('id', 'my-element'))); @@ -250,7 +248,7 @@ suite('Bundler', () => { // document. The first is eager and should be moved. The remaining // one is lazy and should not be moved. const entrypointBundle = - documents.get(resolve('imports/lazy-imports.html'))!.ast; + documents.getHtmlDoc(resolve('imports/lazy-imports.html'))!.ast; const entrypointLazyImports = dom5.queryAll( entrypointBundle, preds.AND(preds.parentMatches(matchers.head), matchers.htmlImport)); @@ -260,7 +258,8 @@ suite('Bundler', () => { // The shared bundle has an inlined dom-module with an embedded // lazy-import via `shared-eager-import-2.html` that we are verifying // is preserved. - const sharedBundle = documents.get(resolve('shared_bundle_1.html'))!.ast; + const sharedBundle = + documents.getHtmlDoc(resolve('shared_bundle_1.html'))!.ast; const sharedLazyImports = dom5.queryAll( sharedBundle, preds.AND( @@ -923,7 +922,8 @@ suite('Bundler', () => { assert.equal(result.manifest.bundles.size, 4); const shell = parse5.serialize( result.documents - .get(resolve('imports/importing-fragments/shell.html'))!.ast); + .getHtmlDoc( + resolve('imports/importing-fragments/shell.html'))!.ast); const fragmentAAt = shell.indexOf('rel="import" href="fragment-a.html"'); const shellAt = shell.indexOf(`console.log('shell.html')`); const sharedUtilAt = shell.indexOf(`console.log('shared-util.html')`); diff --git a/packages/bundler/src/test/shards_test.ts b/packages/bundler/src/test/shards_test.ts index a3c0fd902..50c52059d 100644 --- a/packages/bundler/src/test/shards_test.ts +++ b/packages/bundler/src/test/shards_test.ts @@ -98,13 +98,14 @@ suite('Bundler', () => { [common, entrypoint1, entrypoint2], {strategy: generateSharedDepsMergeStrategy(2)}); assert.equal(documents.size, 4); - const commonDoc = documents.get(common)!.ast; + const commonDoc = documents.get(common)!.ast as dom5.Node; assert.isDefined(commonDoc); - const entrypoint1Doc = documents.get(entrypoint1)!.ast; + const entrypoint1Doc = documents.get(entrypoint1)!.ast as dom5.Node; assert.isDefined(entrypoint1Doc); - const entrypoint2Doc = documents.get(entrypoint2)!.ast; + const entrypoint2Doc = documents.get(entrypoint2)!.ast as dom5.Node; assert.isDefined(entrypoint2Doc); - const sharedDoc = documents.get(resolve('shared_bundle_1.html'))!.ast; + const sharedDoc = + documents.get(resolve('shared_bundle_1.html'))!.ast as dom5.Node; assert.isDefined(sharedDoc); const commonModule = domModulePredicate('common-module'); const elOne = domModulePredicate('el-one'); @@ -129,11 +130,11 @@ suite('Bundler', () => { strategy: generateShellMergeStrategy(analyzer.resolveUrl(shell)!, 2) }); assert.equal(documents.size, 3); - const shellDoc = documents.get(shell)!.ast; + const shellDoc = documents.get(shell)!.ast as dom5.Node; assert.isDefined(shellDoc); - const entrypoint1Doc = documents.get(entrypoint1)!.ast; + const entrypoint1Doc = documents.get(entrypoint1)!.ast as dom5.Node; assert.isDefined(entrypoint1Doc); - const entrypoint2Doc = documents.get(entrypoint2)!.ast; + const entrypoint2Doc = documents.get(entrypoint2)!.ast as dom5.Node; assert.isDefined(entrypoint2Doc); const shellDiv = dom5.predicates.hasAttrValue('id', 'shell'); const shellImport = dom5.predicates.AND( diff --git a/packages/bundler/src/test/sourcemap_test.ts b/packages/bundler/src/test/sourcemap_test.ts index 54be27719..11506a019 100644 --- a/packages/bundler/src/test/sourcemap_test.ts +++ b/packages/bundler/src/test/sourcemap_test.ts @@ -22,7 +22,7 @@ import {MappingItem, RawSourceMap, SourceMapConsumer} from 'source-map'; import {Bundler} from '../bundler'; import {Options as BundlerOptions} from '../bundler'; -import {BundledDocument} from '../document-collection'; +import {BundledHtmlDocument} from '../document-collection'; import * as matchers from '../matchers'; import {getExistingSourcemap} from '../source-map'; import {resolvePath} from '../url-utils'; @@ -35,7 +35,7 @@ suite('Bundler', () => { let bundler: Bundler; async function bundle(inputPath: string, opts?: BundlerOptions): - Promise { + Promise { // Don't modify options directly because test-isolation problems occur. const bundlerOpts = Object.assign({}, opts || {}); if (!bundlerOpts.analyzer) { @@ -47,7 +47,8 @@ suite('Bundler', () => { const manifest = await bundler.generateManifest( [bundler.analyzer.resolveUrl(inputPath as PackageRelativeUrl)!]); const {documents} = await bundler.bundle(manifest); - return documents.get(bundler.analyzer.resolveUrl(inputPath)!)!; + return documents.get(bundler.analyzer.resolveUrl(inputPath)!)! as + BundledHtmlDocument; } function getLine(original: string, lineNum: number) { diff --git a/packages/linter/src/polymer/root-selector-to-html.ts b/packages/linter/src/polymer/root-selector-to-html.ts index 4bdeab517..7a8e1a6a0 100644 --- a/packages/linter/src/polymer/root-selector-to-html.ts +++ b/packages/linter/src/polymer/root-selector-to-html.ts @@ -13,11 +13,11 @@ */ import * as dom5 from 'dom5/lib/index-next'; -import {Document, isPositionInsideRange, ParsedCssDocument, Replacement, Severity, Warning} from 'polymer-analyzer'; +import {Document, isPositionInsideRange, ParsedCssDocument, ParsedHtmlDocument, Replacement, Severity, Warning} from 'polymer-analyzer'; import * as shady from 'shady-css-parser'; +import {HtmlRule} from '../html/rule'; import {registry} from '../registry'; -import {Rule} from '../rule'; import {getDocumentContaining, stripIndentation, stripWhitespace} from '../util'; const p = dom5.predicates; @@ -28,21 +28,19 @@ const isCustomStyle = p.AND( (node: dom5.Node) => !!( node.parentNode && p.hasTagName('custom-style')(node.parentNode)))); -class RootSelectorToHtml extends Rule { +class RootSelectorToHtml extends HtmlRule { code = 'root-selector-to-html'; description = stripIndentation(` Warns when using :root inside an element's template, custom-style, or style module. `); - async check(document: Document) { + async checkDocument(parsedDocument: ParsedHtmlDocument, document: Document) { const elementStyleTags: dom5.Node[] = []; const styleModuleStyleTags: dom5.Node[] = []; // Get custom-styles const customStyleTags = [...dom5.queryAll( - document.parsedDocument.ast, - isCustomStyle, - dom5.childNodesIncludeTemplate)]; + parsedDocument.ast, isCustomStyle, dom5.childNodesIncludeTemplate)]; // Get dom-modules then sort style tags into element styles or style module // styles