diff --git a/addon/nger-demo/template/admin/ng-demo/index.html b/addon/nger-demo/template/admin/ng-demo/index.html new file mode 100644 index 0000000..8abd6df --- /dev/null +++ b/addon/nger-demo/template/admin/ng-demo/index.html @@ -0,0 +1,9 @@ +
+ {{item.title}} +
+
+ {{item.title}} +
+
+ {{item.title}} +
diff --git a/packages/nger-compiler/lib/html/jsx.ts b/addon/nger-demo/template/admin/ng-demo/index.scss similarity index 100% rename from packages/nger-compiler/lib/html/jsx.ts rename to addon/nger-demo/template/admin/ng-demo/index.scss diff --git a/addon/nger-demo/template/admin/ng-demo/index.ts b/addon/nger-demo/template/admin/ng-demo/index.ts new file mode 100644 index 0000000..0726d94 --- /dev/null +++ b/addon/nger-demo/template/admin/ng-demo/index.ts @@ -0,0 +1,8 @@ +import { Page } from 'nger-core'; + +@Page({ + path: '/admin/ng', + templateUrl: './index.html', + styleUrls: ['./index.scss'] +}) +export class NgerDemoAdminNgWelcome { } diff --git a/packages/nger-compiler-preact/lib/transformer_factorys/component.ts b/packages/nger-compiler-preact/lib/transformer_factorys/component.ts index b60e50b..27a78bd 100644 --- a/packages/nger-compiler-preact/lib/transformer_factorys/component.ts +++ b/packages/nger-compiler-preact/lib/transformer_factorys/component.ts @@ -1,5 +1,5 @@ import ts, { TransformationContext, Transformer } from 'typescript'; -import { metadataCache, NgerCompilerNgMetadata, NgerPlatformStyle } from 'nger-compiler'; +import { metadataCache, NgerCompilerNgMetadata, NgerPlatformStyle, NgerCompilerNgTemplate } from 'nger-compiler'; import { Injector } from 'nger-di'; import { FILE_SYSTEM } from 'nger-core'; import { extname, relative, join, dirname } from 'path'; @@ -12,11 +12,13 @@ export const componentTransformerFactory = async (file: string, injector: Inject const fs = injector.get(FILE_SYSTEM); const ng = injector.get(NgerCompilerNgMetadata); const style = injector.get(NgerPlatformStyle); + const ngTemplate = injector.get(NgerCompilerNgTemplate) let styleFile: string = ``; if (metadata) { const component = ng.getComponentConfig(metadata); - let { styles, styleUrls } = component; + let { styles, styleUrls, template, templateUrl, preserveWhitespaces } = component; styles = styles || ``; + template = template || ``; let type: 'less' | 'sass' | 'scss' | 'stylus' | 'css' = 'css' if (styleUrls && styleUrls.length > 0) { styleUrls.map(url => { @@ -32,6 +34,15 @@ export const componentTransformerFactory = async (file: string, injector: Inject styleFile = relative(dirname(styleFile), styleFile); // 生成d.ts } + if (templateUrl) { + const path = join(dirname(file), templateUrl); + template += fs.readFileSync(path).toString('utf8') + } + template = ngTemplate.parse(template, templateUrl || '', { + preserveWhitespaces: !!preserveWhitespaces + }); + // 写入json + } return (context: TransformationContext): Transformer => { return (node: ts.SourceFile): ts.SourceFile => { diff --git a/packages/nger-compiler/lib/bootstrap.ts b/packages/nger-compiler/lib/bootstrap.ts index a922994..20a860f 100644 --- a/packages/nger-compiler/lib/bootstrap.ts +++ b/packages/nger-compiler/lib/bootstrap.ts @@ -6,9 +6,11 @@ import { Injector } from 'nger-di' import { NgerUtil } from 'nger-util' import { WATCH_TASK } from './tokens/watch_task' import { NgerCompilerNgMetadata } from './helper/ng_metadata' +import { NgerCompilerNgTemplate, Node } from './html/ng' import { relative, extname } from 'path'; import { ModuleMetadata } from '@angular/compiler-cli' export let metadataCache: Map = new Map(); +export let templateCache: Map = new Map(); export let hasHandlerFileCache: Set = new Set(); export class NgerCompilerBootstrap extends NgModuleBootstrap { constructor( @@ -42,22 +44,61 @@ export class NgerCompilerBootstrap extends NgModuleBootstrap { } runTask(injector: Injector, path: string, opt: string) { - const fs = injector.get(FILE_SYSTEM) - const stats = fs.statSync(path) - const isTsFile = path.endsWith('.ts') || path.endsWith('.tsx') - if (stats.isFile() && isTsFile && stats.size > 0) { - const ngMetadata = injector.get(NgerCompilerNgMetadata) - const metadata = ngMetadata.getMetadata(path); + try { + const fs = injector.get(FILE_SYSTEM) + const stats = fs.statSync(path) + const isTsFile = path.endsWith('.ts') || path.endsWith('.tsx') const relativePath = relative(root, path) const ext = extname(relativePath); const noExtPath = relativePath.replace(ext, '') - const metadataPath = join(root, '.temp', `${noExtPath}.metadata.json`); - if (metadata) { - fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2)) - metadataCache.set(path, metadata); + if (stats.isFile() && isTsFile && stats.size > 0) { + const ngMetadata = injector.get(NgerCompilerNgMetadata) + const metadata = ngMetadata.getMetadata(path); + const metadataPath = join(root, '.temp', `${noExtPath}.metadata.json`); + if (metadata) { + fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2)) + metadataCache.set(path, metadata); + } } - } - const tasks = injector.get(WATCH_TASK); - tasks.map(task => task(path, opt, injector)); + const isHtmlFile = path.endsWith('.html'); + if (isHtmlFile) { + const ngTpl = injector.get(NgerCompilerNgTemplate); + const code = fs.readFileSync(path).toString('utf8') + const metadata = ngTpl.parse(code, path); + const metadataPath = join(root, '.temp', `${noExtPath}.template.json`); + if (metadata) { + try { + const res = clearHtmlTemplate(metadata); + fs.writeFileSync(metadataPath, JSON.stringify(res, null, 2)) + templateCache.set(path, metadata); + } catch (e) { + console.log(`${e.message}\n${e.stack}`) + } + } + } + const tasks = injector.get(WATCH_TASK); + tasks.map(task => task(path, opt, injector)); + } catch (e) { } + } +} + +function clearHtmlTemplate(json: any) { + if (Array.isArray(json)) { + return json.map(item => clearHtmlTemplate(item)) + } else if (!!json && typeof json === 'object') { + const res: any = {}; + Object.keys(json).map(key => { + if (key === 'sourceSpan') { } + else if (key === 'span') { } + else if (key === 'location') { } + else if (key === 'startSourceSpan') { } + else if (key === 'endSourceSpan') { } + else { + res[key] = clearHtmlTemplate(json[key]) + } + }) + return res; + } else { + return json; } } \ No newline at end of file diff --git a/packages/nger-compiler/lib/html/ng.ts b/packages/nger-compiler/lib/html/ng.ts index 6284cd8..869dff0 100644 --- a/packages/nger-compiler/lib/html/ng.ts +++ b/packages/nger-compiler/lib/html/ng.ts @@ -1,5 +1,6 @@ import { parseTemplate } from '@angular/compiler' import { Injectable } from 'nger-core' +import { Node } from '@angular/compiler/src/render3/r3_ast' export interface ParseTemplateOptions { preserveWhitespaces?: boolean; interpolationConfig?: InterpolationConfig; @@ -12,7 +13,10 @@ export declare class InterpolationConfig { } @Injectable() export class NgerCompilerNgTemplate { - parse(template: string, templateUrl: string, options?: ParseTemplateOptions) { - return parseTemplate(template, templateUrl, options) + parse(template: string, templateUrl: string, options?: ParseTemplateOptions): Node[] { + const nodes = parseTemplate(template, templateUrl, options).nodes + return nodes; } -} \ No newline at end of file +} + +export { Node } \ No newline at end of file diff --git a/packages/nger-compiler/lib/html/type.ts b/packages/nger-compiler/lib/html/type.ts deleted file mode 100644 index d4b89d2..0000000 --- a/packages/nger-compiler/lib/html/type.ts +++ /dev/null @@ -1,56 +0,0 @@ -export type Ref = (instance: T) => void; -export type ComponentChild = VNode | object | string | number | boolean | null; -export type ComponentChildren = ComponentChild[] | ComponentChild; -interface Attributes { - key?: Key; - jsx?: boolean; -} -interface Component

{ - componentWillMount?(): void; - componentDidMount?(): void; - componentWillUnmount?(): void; - getChildContext?(): object; - componentWillReceiveProps?(nextProps: Readonly

, nextContext: any): void; - shouldComponentUpdate?(nextProps: Readonly

, nextState: Readonly, nextContext: any): boolean; - componentWillUpdate?(nextProps: Readonly

, nextState: Readonly, nextContext: any): void; - componentDidUpdate?(previousProps: Readonly

, previousState: Readonly, previousContext: any): void; -} -type RenderableProps = Readonly< - P & Attributes & { children?: ComponentChildren; ref?: Ref } ->; -interface ComponentConstructor

{ - new(props: P, context?: any): Component; - displayName?: string; - defaultProps?: Partial

; -} -interface FunctionalComponent

{ - (props: RenderableProps

, context?: any): VNode | null; - displayName?: string; - defaultProps?: Partial

; -} -export type Key = string | number; -export type ComponentFactory

= ComponentConstructor

| FunctionalComponent

; -export interface VNode

{ - nodeName: ComponentFactory

| string; - attributes: P; - children: Array | string>; - key?: Key | null; -} -interface Options { - shallow?: boolean; - xml?: boolean; - pretty?: boolean | string; - sortAttributes?: boolean; - allAttributes?: boolean; - attributeHook?: any; -} - -// Element P 输入属性对应input,output -export interface NgElement

{ - -} -declare global { - namespace JSX { - interface Element extends NgElement { } - } -} \ No newline at end of file diff --git a/packages/nger-compiler/lib/index.ts b/packages/nger-compiler/lib/index.ts index 862fdc3..5166ca5 100644 --- a/packages/nger-compiler/lib/index.ts +++ b/packages/nger-compiler/lib/index.ts @@ -11,7 +11,7 @@ import { NgerCompilerCid } from './helper/cid' import { NgerCompilerNgMetadata } from './helper/ng_metadata' import { controllerPropertyTransformerFactory, hasPropertyMetadata } from './transformer_factorys/controller' import { WATCH_TASK, Task } from './tokens/watch_task' -import { NgerCompilerBootstrap, metadataCache, hasHandlerFileCache } from './bootstrap' +import { NgerCompilerBootstrap, metadataCache, hasHandlerFileCache, templateCache } from './bootstrap' import { controllerVisitor } from './visitors/controller' import { NgModuleBootstrap } from 'nger-core' import { NgerUtil } from 'nger-util' @@ -30,7 +30,8 @@ export { Task, hasPropertyMetadata, metadataCache, - hasHandlerFileCache + hasHandlerFileCache, + templateCache } const provides: StaticProvider[] = [ ...styleProviders,