Skip to content

Commit

Permalink
feat: support nsPrefix for each render
Browse files Browse the repository at this point in the history
  • Loading branch information
harttle committed Oct 18, 2019
1 parent 9ea684d commit 16d7e1c
Show file tree
Hide file tree
Showing 12 changed files with 49 additions and 64 deletions.
2 changes: 1 addition & 1 deletion bin/render.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
$data = getData($caseDir);

$noDataOutput = preg_match('/-ndo$/', $caseName);
$renderFunc = '\\san\\renderer\\' . dashesToCamelCase($caseName) . '\\render';
$renderFunc = '\\san\\' . dashesToCamelCase($caseName) . '\\renderer\\render';

echo $renderFunc($data, $noDataOutput);

Expand Down
6 changes: 3 additions & 3 deletions runtime/underscore.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ private static function boolAttrTruthy($value) {

public static function getClassByCtx($ctx) {
$cid = $ctx->sanssrCid;
if (\san\runtime\ComponentRegistry::has($cid)) {
return \san\runtime\ComponentRegistry::get($cid);
if (\__NSPREFIX__runtime\ComponentRegistry::has($cid)) {
return \__NSPREFIX__runtime\ComponentRegistry::get($cid);
}
return null;
}
Expand All @@ -196,7 +196,7 @@ public static function callFilter($ctx, $name, $args)
public static function createComponent (&$ctx) {
$cls = _::getClassByCtx($ctx);
if (!class_exists($cls)) {
$cls = "\\san\\runtime\\Component";
$cls = '\__NSPREFIX__runtime\Component';
}
$obj = new $cls();
$obj->data = new Data($ctx);
Expand Down
8 changes: 4 additions & 4 deletions src/compilers/component-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ export class ComponentRegistry {
}
}

writeComponentRegistry (ns: (file: string) => string, emitter: PHPEmitter) {
emitter.beginNamespace('san\\runtime')
writeComponentRegistry (nsPrefix: string, ns: (file: string) => string, emitter: PHPEmitter) {
emitter.beginNamespace(`${nsPrefix}runtime`)
emitter.writeLine(`ComponentRegistry::$comps = [`)
emitter.indent()

const lines = []
for (const [cid, { name, path }] of this.components) {
const classReference = `\\${ns(path)}\\${name}`
lines.push(`"${cid}" => "${classReference.replace(/\\/g, '\\\\')}"`)
const classReference = `\\${nsPrefix}${ns(path)}\\${name}`
lines.push(`"${cid}" => '${classReference}'`)
}
emitter.writeLines(lines.join(',\n'))

Expand Down
14 changes: 8 additions & 6 deletions src/compilers/php-render-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { each, extend } from '../utils/underscore'
import { PHPEmitter } from '../emitters/php-emitter'
import { ExpressionEmitter } from '../emitters/expression-emitter'

let ssrIndex = 0
let namespacePrefix = ''

/**
* 将字符串逗号切分返回对象
*
Expand Down Expand Up @@ -395,8 +398,6 @@ function camelComponentBinds (binds) {
return result
}

let ssrIndex = 0

function genSSRId () {
return 'sanssrId' + (ssrIndex++)
}
Expand Down Expand Up @@ -445,7 +446,7 @@ const stringifier = {
},

date: function (source) {
return 'new \\san\\runtime\\Ts2Php_Date(' + source.getTime() + ')'
return `new \\${namespacePrefix}runtime\\Ts2Php_Date(` + source.getTime() + ')'
},

any: function (source) {
Expand Down Expand Up @@ -1192,14 +1193,15 @@ function genComponentContextCode (component, emitter) {
export function generateRenderModule ({
ComponentClass,
funcName = '',
ns = 'san\\renderer',
nsPrefix = '',
emitter = new PHPEmitter()
}) {
namespacePrefix = nsPrefix
if (typeof ComponentClass !== 'function') {
throw new Error('ComponentClass is needed to generate render function')
}
emitter.beginNamespace(ns)
emitter.writeLine(`use \\san\\runtime\\_;`)
emitter.beginNamespace(nsPrefix + 'renderer')
emitter.writeLine(`use ${nsPrefix}runtime\\_;`)
ssrIndex = 0

const contextId = genSSRId()
Expand Down
5 changes: 3 additions & 2 deletions src/compilers/to-js-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getDefaultConfigPath } from '../parsers/tsconfig'
import { sep, extname } from 'path'
import debugFactory from 'debug'
import { Compiler } from './compiler'
import { emitRuntimeInJS } from '../emitters/runtime'

const debug = debugFactory('to-js-compiler')

Expand Down Expand Up @@ -48,7 +49,7 @@ export class ToJSCompiler implements Compiler {
const emitter = new JSEmitter()
emitter.write('module.exports = ')
emitter.writeAnonymousFunction(['data', 'noDataOutput'], () => {
emitter.writeRuntime()
emitRuntimeInJS(emitter)
const componentClass = new CommonJS().require(filepath)
emitter.writeLines(generateRenderFunction(componentClass))
})
Expand All @@ -60,7 +61,7 @@ export class ToJSCompiler implements Compiler {
const emitter = new JSEmitter()
emitter.write('module.exports = ')
emitter.writeAnonymousFunction(['data', 'noDataOutput'], () => {
emitter.writeRuntime()
emitRuntimeInJS(emitter)
const parser = new ComponentParser(this.project)
const component = parser.parseComponent(filepath)
const componentClass = this.evalComponentClass(component)
Expand Down
52 changes: 23 additions & 29 deletions src/compilers/to-php-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,28 @@ import { getDefaultConfigPath } from '../parsers/tsconfig'
import { sep, extname } from 'path'
import debugFactory from 'debug'
import { Compiler } from './compiler'
import { emitRuntimeInPHP } from '../emitters/runtime'

const debug = debugFactory('ast-util')

export type ToPHPCompilerOptions = {
tsConfigFilePath?: string,
root?: string,
externalModules?: ModuleInfo[],
nsPrefix?: string
externalModules?: ModuleInfo[]
}

export class ToPHPCompiler implements Compiler {
private root: string
private tsConfigFilePath: string
private nsPrefix: string
private externalModules: ModuleInfo[]
private toJSCompiler: ToJSCompiler
private project: Project

constructor ({
tsConfigFilePath = getDefaultConfigPath(),
root = tsConfigFilePath.split(sep).slice(0, -1).join(sep),
externalModules = [],
nsPrefix = ''
externalModules = []
}: ToPHPCompilerOptions = {}) {
this.nsPrefix = nsPrefix
this.externalModules = [{
name: 'san-ssr',
required: true
Expand All @@ -67,41 +64,41 @@ export class ToPHPCompiler implements Compiler {

public compileFromTS (filepath: string, {
funcName = 'render',
ns = 'san\\renderer',
nsPrefix = 'san\\',
emitHeader = true
} = {}) {
const emitter = new PHPEmitter(emitHeader)
const parser = new ComponentParser(this.project)
const component = parser.parseComponent(filepath)
const ComponentClass = this.toJSCompiler.evalComponentClass(component)

generateRenderModule({ ComponentClass, funcName, emitter, ns })
this.compileComponents(component, emitter)
generateRenderModule({ ComponentClass, funcName, emitter, nsPrefix })
this.compileComponents(component, emitter, nsPrefix)

emitter.writeRuntime()
emitRuntimeInPHP(emitter, nsPrefix)
return emitter.fullText()
}

public compileFromJS (filepath: string, {
funcName = 'render',
ns = 'san\\renderer',
nsPrefix = 'san\\',
emitHeader = true
} = {}) {
const emitter = new PHPEmitter(emitHeader)

const ComponentClass = new CommonJS().require(filepath)
generateRenderModule({ ComponentClass, funcName, emitter, ns })
generateRenderModule({ ComponentClass, funcName, emitter, nsPrefix })

emitter.writeRuntime()
emitRuntimeInPHP(emitter, nsPrefix)
return emitter.fullText()
}

public compileToPHP (sourceFile: SanSourceFile) {
public compileToPHP (sourceFile: SanSourceFile, nsPrefix = '') {
transformAstToPHP(sourceFile)
const tsconfig = require(this.tsConfigFilePath)
const externalModules = [...this.externalModules]
for (const decl of getInlineDeclarations(sourceFile.origin)) {
const ns = this.ns(decl.getModuleSpecifierSourceFile().getFilePath())
const ns = nsPrefix + this.ns(decl.getModuleSpecifierSourceFile().getFilePath())
const literal = decl.getModuleSpecifierValue()
externalModules.push({
name: literal,
Expand All @@ -112,34 +109,31 @@ export class ToPHPCompiler implements Compiler {
return generatePHPCode(
sourceFile,
externalModules,
tsconfig['compilerOptions']
tsconfig['compilerOptions'],
nsPrefix
)
}

public compileComponents (entryComp: Component, emitter: PHPEmitter = new PHPEmitter()) {
public compileComponents (entryComp: Component, emitter: PHPEmitter = new PHPEmitter(), nsPrefix = '') {
const registry = new ComponentRegistry()
for (const [path, sourceFile] of entryComp.getFiles()) {
registry.registerComponents(sourceFile)

emitter.beginNamespace(this.ns(path))
emitter.writeLine('use \\san\\runtime\\_;')
emitter.writeLine('use \\san\\runtime\\Component;')
emitter.writeLines(this.compileToPHP(sourceFile))
emitter.beginNamespace(nsPrefix + this.ns(path))
emitter.writeLine(`use ${nsPrefix}runtime\\_;`)
emitter.writeLine(`use ${nsPrefix}runtime\\Component;`)
emitter.writeLines(this.compileToPHP(sourceFile, nsPrefix))
emitter.endNamespace()
}
registry.writeComponentRegistry(path => this.ns(path), emitter)
registry.writeComponentRegistry(nsPrefix, path => this.ns(path), emitter)
return emitter.fullText()
}

private ns (file) {
private ns (file: string) {
const escapeName = x => isReserved(x) ? 'sanssrNS' + camelCase(x) : x
let str = file
return file
.slice(this.root.length, -extname(file).length)
.split(sep).map(camelCase).map(escapeName).join('\\')
.split(sep).map(x => camelCase(x)).map(escapeName).join('\\')
.replace(/^\\/, '')
if (this.nsPrefix) {
str = this.nsPrefix + str
}
return str
}
}
1 change: 0 additions & 1 deletion src/emitters/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export abstract class Emitter {
}

public abstract write (str: string)
public abstract writeRuntime ()
public fullText () {
return this.code
}
Expand Down
4 changes: 2 additions & 2 deletions src/emitters/generate-php-code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ export type ModuleInfo = {
namespace?: string
}

export function generatePHPCode (sourceFile: SanSourceFile, modules: ModuleInfo[], compilerOptions) {
export function generatePHPCode (sourceFile: SanSourceFile, modules: ModuleInfo[], compilerOptions, nsPrefix: string) {
debug('modules:', modules)
const options = {
source: sourceFile.getFullText(),
emitHeader: false,
plugins: [],
modules: keyBy(modules, 'name'),
helperNamespace: '\\san\\runtime\\',
helperNamespace: `\\${nsPrefix}runtime\\`,
compilerOptions
}
const { errors, phpCode } = compile(sourceFile.getFilePath(), options)
Expand Down
5 changes: 0 additions & 5 deletions src/emitters/js-emitter.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { Emitter } from './emitter'
import { emitRuntimeInJS } from './runtime'

export class JSEmitter extends Emitter {
public writeRuntime () {
emitRuntimeInJS(this)
}

public write (str: string) {
return this.defaultWrite(str)
}
Expand Down
5 changes: 0 additions & 5 deletions src/emitters/php-emitter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Emitter } from './emitter'
import { ExpressionEmitter } from './expression-emitter'
import { emitRuntimeInPHP } from './runtime'

export class PHPEmitter extends Emitter {
buffer: string = ''
Expand All @@ -15,10 +14,6 @@ export class PHPEmitter extends Emitter {
return this.defaultWrite(str)
}

public writeRuntime () {
emitRuntimeInPHP(this)
}

public beginNamespace (ns: string = '') {
const code = ns === ''
? 'namespace {'
Expand Down
6 changes: 3 additions & 3 deletions src/emitters/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ const runtimeFiles = [
'component-registry.php'
]

export function emitRuntimeInPHP (emitter: PHPEmitter) {
emitter.beginNamespace('san\\runtime')
export function emitRuntimeInPHP (emitter: PHPEmitter, nsPrefix: string) {
emitter.beginNamespace(nsPrefix + 'runtime')
for (const file of runtimeFiles) {
const path = resolve(__dirname, `../../runtime/${file}`)
emitter.writeLines(readPHPSource(path))
emitter.writeLines(readPHPSource(path).replace(/__NSPREFIX__/g, nsPrefix))
}
emitter.endNamespace()
return emitter.fullText()
Expand Down
5 changes: 2 additions & 3 deletions src/utils/case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ const cases = readdirSync(caseRoot)
const toJSCompiler = new ToJSCompiler({ tsConfigFilePath })
const toPHPCompiler = new ToPHPCompiler({
tsConfigFilePath,
externalModules: [{ name: '../../..', required: true }],
nsPrefix: 'san\\components\\test\\'
externalModules: [{ name: '../../..', required: true }]
})
const multiFileCases = ['multi-component-files', 'multi-files']

Expand All @@ -41,7 +40,7 @@ export function compileToPHP (caseName) {
const js = resolve(caseRoot, caseName, 'component.js')
const targetCode = toPHPCompiler.compile(
existsSync(ts) ? ts : js,
{ ns: `san\\renderer\\${camelCase(caseName)}` }
{ nsPrefix: `san\\${camelCase(caseName)}\\` }
)

writeFileSync(join(caseRoot, caseName, 'ssr.php'), targetCode)
Expand Down

0 comments on commit 16d7e1c

Please sign in to comment.