Skip to content

Commit

Permalink
Merge pull request #169 from mgechev/html-css-dsls
Browse files Browse the repository at this point in the history
feat: supports html & css dsls through sourcemaps
  • Loading branch information
mgechev committed Nov 27, 2016
2 parents 67d5a07 + 9c86755 commit 1ca7068
Show file tree
Hide file tree
Showing 29 changed files with 613 additions and 266 deletions.
40 changes: 40 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# AppVeyor file
# http://www.appveyor.com/docs/appveyor-yml
# This file: cloned from https://github.com/gruntjs/grunt/blob/master/appveyor.yml

# Build version format
version: "{build}"

# Test against this version of Node.js
environment:
nodejs_version: "Stable"

build: off

clone_depth: 10

# Fix line endings on Windows
init:
- git config --global core.autocrlf true

install:
- ps: Install-Product node $env:nodejs_version
- npm install -g npm@3.10.8
- ps: $env:path = $env:appdata + "\npm;" + $env:path
- npm install

test_script:
# Output useful info for debugging.
- node --version && npm --version
# We test multiple Windows shells because of prior stdout buffering issues
# filed against Grunt. https://github.com/joyent/node/issues/3584
- ps: "npm --version # PowerShell" # Pass comment to PS for easier debugging
- npm t

notifications:
- provider: Webhook
url: https://webhooks.gitter.im/e/cfd8ce5ddee6f3a0b0c9
on_build_success: false
on_build_failure: true
on_build_status_changed: true

9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"copy:common": "cp README.md dist",
"build:links": "ts-node build/links.ts --src ./dist",
"prepare:package": "cat package.json | ts-node build/package.ts > dist/package.json",
"test": "rimraf dist && tsc && cp -r test/fixtures dist/test && mocha dist/test/** dist/test/** --recursive",
"test:watch": "rimraf dist && tsc && cp -r test/fixtures dist/test && mocha dist/test/** dist/test/** --watch --recursive",
"test": "rimraf dist && tsc && cp -r test/fixtures dist/test && mocha dist/test --recursive",
"test:watch": "rimraf dist && tsc && cp -r test/fixtures dist/test && mocha dist/test --watch --recursive",
"tscv": "tsc --version",
"tsc": "tsc",
"tsc:watch": "tsc --w"
Expand Down Expand Up @@ -46,13 +46,17 @@
"@angular/compiler": "^2.2.0",
"@angular/core": "^2.2.0",
"@types/chai": "^3.4.33",
"@types/less": "0.0.31",
"@types/mocha": "^2.2.32",
"@types/node": "^6.0.41",
"@types/node-sass": "^3.10.31",
"@types/source-map": "^0.5.0",
"@types/sprintf-js": "0.0.27",
"chai": "^3.5.0",
"chai-spies": "^0.7.1",
"minimalist": "1.0.0",
"mocha": "3.0.2",
"node-sass": "^3.13.0",
"rimraf": "^2.5.2",
"rxjs": "5.0.0-beta.12",
"ts-node": "1.2.2",
Expand All @@ -69,6 +73,7 @@
"app-root-path": "^2.0.1",
"css-selector-tokenizer": "^0.7.0",
"cssauron": "^1.4.0",
"source-map": "^0.5.6",
"sprintf-js": "^1.0.3"
}
}
45 changes: 36 additions & 9 deletions src/angular/config.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,66 @@
import * as ts from 'typescript';

const root = require('app-root-path');
const join = require('path').join;
import {CodeWithSourceMap} from './metadata';

export interface UrlResolver {
(url: string, d: ts.Decorator): string;
}

export interface TemplateTransformer {
(template: string, url: string, d: ts.Decorator): CodeWithSourceMap;
}

export interface StyleTransformer {
(style: string, url: string, d: ts.Decorator): CodeWithSourceMap;
}

export const LogLevel = {
None: 0,
Error: 0b001,
Info: 0b011,
Debug: 0b111
};

export interface Config {
interpolation: [string, string];
resolveUrl: UrlResolver;
transformTemplate: TemplateTransformer;
transformStyle: StyleTransformer;
predefinedDirectives: DirectiveDeclaration[];
basePath: string;
logLevel: number;
}

export interface DirectiveDeclaration {
selector: string;
exportAs: string;
}

export let Config: Config = {
export const Config: Config = {
interpolation: ['{{', '}}'],

resolveUrl(url: string, d: ts.Decorator) {
return url;
},

transformTemplate(code: string, url: string, d: ts.Decorator) {
return { code, url };
},

transformStyle(code: string, url: string, d: ts.Decorator) {
return { code, url };
},

predefinedDirectives: [
{ selector: 'form', exportAs: 'ngForm' }
],
basePath: ''

logLevel: LogLevel.None
};

const root = require('app-root-path');

try {
let newConfig = require(join(root.path, '.codelyzer'));
let newConfig = require(root.path + '/.codelyzer');
Object.assign(Config, newConfig);
} catch (e) {

console.info('Cannot find ".codelyzer.js" in the root of the project');
}

1 change: 0 additions & 1 deletion src/angular/fileResolver/fileResolver.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export abstract class FileResolver {
abstract resolve(path: string): string;
}

15 changes: 11 additions & 4 deletions src/angular/metadata.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import * as ts from 'typescript';
import {RawSourceMap} from 'source-map';

export interface CodeWithSourceMap {
code: string;
source?: string;
map?: RawSourceMap;
}

export interface TemplateMetadata {
template: string;
template: CodeWithSourceMap;
node: ts.Node;
source: string;
url: string;
}

export interface StyleMetadata {
style: string;
style: CodeWithSourceMap;
node: ts.Node;
source: string;
url: string;
}

export interface StylesMetadata {
Expand Down
114 changes: 71 additions & 43 deletions src/angular/metadataReader.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
import * as ts from 'typescript';
import {current} from '../util/syntaxKind';
import {isSimpleTemplateString, getDecoratorPropertyInitializer} from '../util/utils';

const kinds = current();

import {FileResolver} from './fileResolver/fileResolver';
import {AbstractResolver} from './urlResolvers/abstractResolver';
import {AbstractResolver, MetadataUrls} from './urlResolvers/abstractResolver';
import {UrlResolver} from './urlResolvers/urlResolver';
import {PathResolver} from './urlResolvers/pathResolver';

import {logger} from '../util/logger';
import {isSimpleTemplateString, getDecoratorPropertyInitializer} from '../util/utils';

import {Config} from './config';

import {DirectiveMetadata, ComponentMetadata, StylesMetadata} from './metadata';
import {DirectiveMetadata, ComponentMetadata, StylesMetadata, CodeWithSourceMap, TemplateMetadata} from './metadata';

const kinds = current();

const normalizeTransformed = (t: CodeWithSourceMap) => {
if (!t.map) {
t.source = t.code;
}
return t;
};

/**
* For async implementation https://gist.github.com/mgechev/6f2245c0dfb38539cc606ea9211ecb37
*/
export class MetadataReader {

constructor(private _fileResolver: FileResolver, private _urlResolver?: AbstractResolver) {
this._urlResolver = this._urlResolver || new UrlResolver();
this._urlResolver = this._urlResolver || new UrlResolver(new PathResolver());
}

read(d: ts.ClassDeclaration): DirectiveMetadata {
Expand Down Expand Up @@ -61,62 +77,75 @@ export class MetadataReader {
return metadata;
}

readComponentMetadata(d: ts.ClassDeclaration, dec: ts.Decorator) {
const expr = this.getDecoratorArgument(dec);
const metadata = this.readDirectiveMetadata(d, dec);
const result = new ComponentMetadata();
if (!expr) {
return result;
}
result.selector = metadata.selector;
result.controller = metadata.controller;
readComponentTemplateMetadata(dec: ts.Decorator, external: MetadataUrls): TemplateMetadata {
const inlineTemplate = getDecoratorPropertyInitializer(dec, 'template');
const external = this._urlResolver.resolve(dec);
if (inlineTemplate && isSimpleTemplateString(inlineTemplate)) {
result.template = {
template: inlineTemplate.text,
source: null,
const transformed = normalizeTransformed(Config.transformTemplate(inlineTemplate.text, null, dec));
return {
template: transformed,
url: null,
node: inlineTemplate
};
} else {
if (external.templateUrl) {
try {
const template = this._fileResolver.resolve(external.templateUrl);
const transformed = normalizeTransformed(Config.transformTemplate(template, external.templateUrl, dec));
return {
template: transformed,
url: external.templateUrl,
node: null
};
} catch (e) {
logger.info('Cannot read the external template ' + external.templateUrl);
}
}
}
}

readComponentStylesMetadata(dec: ts.Decorator, external: MetadataUrls) {
const inlineStyles = getDecoratorPropertyInitializer(dec, 'styles');
let styles: any[];
if (inlineStyles && inlineStyles.kind === kinds.ArrayLiteralExpression) {
inlineStyles.elements.forEach((inlineStyle: any) => {
if (isSimpleTemplateString(inlineStyle)) {
result.styles = result.styles || [];
result.styles.push({
style: inlineStyle.text,
source: null,
node: inlineStyle
styles = styles || [];
styles.push({
style: normalizeTransformed(Config.transformStyle(inlineStyle.text, null, dec)),
url: null,
node: inlineStyle,
});
}
});
}
if (!result.template && external.templateUrl) {
} else if (external.styleUrls) {
try {
result.template = {
template: this._fileResolver.resolve(external.templateUrl),
source: external.templateUrl,
node: null
};
} catch (e) {
console.log(e);
console.log('Cannot read the external template ' + external.templateUrl);
}
}
if (!result.styles || !result.styles.length) {
try {
result.styles = <any>external.styleUrls.map((url: string) => {
styles = <any>external.styleUrls.map((url: string) => {
const style = this._fileResolver.resolve(url);
const transformed = normalizeTransformed(Config.transformStyle(style, url, dec));
return {
style: this._fileResolver.resolve(url),
source: url,
style: transformed, url,
node: null
};
});
} catch (e) {
console.log('Unable to read external style. ' + e.toString());
logger.info('Unable to read external style. ' + e.toString());
}
}
return styles;
}

readComponentMetadata(d: ts.ClassDeclaration, dec: ts.Decorator) {
const expr = this.getDecoratorArgument(dec);
const metadata = this.readDirectiveMetadata(d, dec);
const result = new ComponentMetadata();
result.selector = metadata.selector;
result.controller = metadata.controller;
if (!expr) {
return result;
}
const external = this._urlResolver.resolve(dec);
result.template = this.readComponentTemplateMetadata(dec, external);
result.styles = this.readComponentStylesMetadata(dec, external);
return result;
}

Expand All @@ -131,4 +160,3 @@ export class MetadataReader {
return null;
}
}

Loading

0 comments on commit 1ca7068

Please sign in to comment.