diff --git a/README.md b/README.md index 06e0eb2d..6bde1981 100644 --- a/README.md +++ b/README.md @@ -10,24 +10,37 @@ This is [San][san] SSR for PHP environment. - [x] create a simplified JS SSR for reference - [x] migrate all SSR cases from baidu/san - [x] migrate all e2e cases from baidu/san - - [x] debug scripts and Zsh auto completion 1. Basic Templating - [x] implement runtime utils in PHP - [x] introduce emitter and apply to php-ssr - [x] beautify the output - [x] pass all template-only test cases + - [x] debug scripts and Zsh auto completion + - [ ] CLI support + - [ ] travis CI + - [ ] semantic release 2. Bussiness Logic to PHP - [x] compile source files to php: make use of ts2php - [x] compile component files to php - [x] parse files to AST to bind sourcecode info to runtime - [x] wireup ssr.php and component.php - [x] pass all test cases using filters/computed - - [ ] allow `import {Component} from 'san'` as well as `import * as san` - - [ ] support anonymous component class, aka `export default class extends Component {}` + - [ ] set FilterDeclarations, ComputedDeclarations types if not declared 3. Multiple Source Files - [x] a virtual CommonJS to load AST transformed sourceFiles - [x] support multiple source files for a single component - [x] support nested components in multiple files +4. Misc. + - support anonymous default export: `export default class extends Component {}` + - check default export and throw a more spcific Error + - check default export extends Component + - support SyntheticDefaultImports: `import * as san` + +## PHP SSR Problems + +THIS SECTION IS FOR MAINTAINERS ONLY + +- filters/computed 是 static,这要求使用时额外声明其类型 ## JS SSR Problems diff --git a/package-lock.json b/package-lock.json index 67fcaba5..a8f91a62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1522,9 +1522,9 @@ "dev": true }, "@types/yargs": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.2.tgz", - "integrity": "sha512-lwwgizwk/bIIU+3ELORkyuOgDjCh7zuWDFqRtPPhhVgq9N1F7CvLNKg1TX4f2duwtKQ0p044Au9r1PLIXHrIzQ==", + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", + "integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -5202,6 +5202,21 @@ "jest-cli": "^24.9.0" }, "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, "jest-cli": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", @@ -5221,6 +5236,96 @@ "prompts": "^2.0.1", "realpath-native": "^1.1.0", "yargs": "^13.3.0" + }, + "dependencies": { + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -5535,7 +5640,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -5950,7 +6056,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6006,6 +6113,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6049,12 +6157,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -6396,17 +6506,120 @@ "yargs": "^13.3.0" }, "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, @@ -9506,16 +9719,82 @@ "yargs": "^13.2.4" }, "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, "code-block-writer": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-9.4.1.tgz", "integrity": "sha512-LHAB+DL4YZDcwK8y/kAxZ0Lf/ncwLh/Ux4cTVWbPwIdrf1gPxXiPcwpz8r8/KqXu1aD+Raz46EOxDjFlbyO6bA==" }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, "ts-morph": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-3.1.3.tgz", @@ -9542,6 +9821,32 @@ } } } + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, @@ -10074,11 +10379,12 @@ "dev": true }, "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.0.tgz", + "integrity": "sha512-/is78VKbKs70bVZH7w4YaZea6xcJWOAwkhbR0CFuZBmYtfTYF0xjGJF43AYd8g2Uii1yJwmS5GR2vBmrc32sbg==", "requires": { "cliui": "^5.0.0", + "decamelize": "^1.2.0", "find-up": "^3.0.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", @@ -10087,7 +10393,7 @@ "string-width": "^3.0.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "yargs-parser": "^15.0.0" }, "dependencies": { "ansi-regex": { @@ -10159,19 +10465,12 @@ } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz", + "integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==", "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - } } }, "yeast": { diff --git a/package.json b/package.json index 4f516b04..ddcbefe9 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,9 @@ "directories": { "test": "test" }, + "bin": { + "ssp": "./dist/bin/ssp.js" + }, "scripts": { "lint": "eslint src test", "build": "tsc", @@ -36,6 +39,7 @@ "@babel/runtime": "^7.6.0", "@jest/transform": "^24.9.0", "@types/jest": "^24.0.18", + "@types/yargs": "^13.0.3", "@typescript-eslint/eslint-plugin": "^2.0.0", "@typescript-eslint/parser": "^2.0.0", "babel-jest": "^24.9.0", @@ -70,6 +74,7 @@ "snake-case": "^2.1.0", "ts-morph": "^4.0.1", "ts2php": "^0.12.3", - "typescript": "^3.4.5" + "typescript": "^3.4.5", + "yargs": "^14.2.0" } } diff --git a/runtime/underscore.php b/runtime/underscore.php index b4041120..05223f0b 100644 --- a/runtime/underscore.php +++ b/runtime/underscore.php @@ -164,7 +164,7 @@ private static function boolAttrTruthy($value) { } public static function getClassByCtx($ctx) { - $cid = $ctx->spsrCid; + $cid = $ctx->sspCid; if (\san\runtime\ComponentRegistry::has($cid)) { return \san\runtime\ComponentRegistry::get($cid); } diff --git a/src/bin/ssp.ts b/src/bin/ssp.ts new file mode 100755 index 00000000..360f1d15 --- /dev/null +++ b/src/bin/ssp.ts @@ -0,0 +1,66 @@ +#!/usr/bin/env node + +import chalk from 'chalk' +import { ToPHPCompiler } from '../compilers/to-php-compiler' +import { ToJSCompiler } from '../compilers/to-js-compiler' +import { writeFileSync } from 'fs' +import { extname, resolve } from 'path' +import * as yargs from 'yargs' + +type OptionValue = string | undefined + +yargs + .usage('$0 [OPTION]... ') + .option('output', { + alias: 'o', + description: 'output file path, output to STDOUT if not specified' + }) + .option('target', { + alias: 't', + default: 'php', + choices: ['php', 'js'], + description: 'target SSR file' + }) + .option('tsconfig', { + alias: 'c', + description: 'tsconfig path, will auto resolve if not specified' + }) + .check(argv => { + if (argv._.length === 0) { + throw new Error('component file must be provided') + } + return true + }) + +const target = yargs.argv.target as OptionValue +const tsConfigFilePath = yargs.argv.tsconfig as OptionValue +const output = yargs.argv.output as OptionValue +const componentFile = resolve(yargs.argv._[0]) + +if (target === 'php') { + console.error(chalk.gray('compiling'), componentFile, 'to', target) + const toPHPCompiler = new ToPHPCompiler({ + tsConfigFilePath, + externalModules: [{ name: '../../..', required: true }], + nsPrefix: 'san\\components\\test\\' + }) + const ext = extname(componentFile) + const options = { + ns: `san\\renderer` + } + let targetCode = '' + if (ext === '.ts') { + targetCode = toPHPCompiler.compileFromTS(componentFile, options) + } else if (ext === '.js') { + targetCode = toPHPCompiler.compileFromJS(componentFile, options) + } else { + throw new Error(`not recognized file extension: ${ext}`) + } + if (output !== undefined) { + writeFileSync(output, targetCode) + } else { + console.log(targetCode) + } +} + +// const toJSCompiler = new ToJSCompiler(tsConfigFilePath) diff --git a/src/compilers/php-render-compiler.ts b/src/compilers/php-render-compiler.ts index 08156ade..71e13176 100644 --- a/src/compilers/php-render-compiler.ts +++ b/src/compilers/php-render-compiler.ts @@ -1,6 +1,6 @@ /** * 将组件树编译成 render 函数之间的递归调用 - * 提供 compileRenderFunction 方法 + * 提供 generateRenderFunction 方法 */ import { each, extend, inherits } from '../utils/underscore' import { createAccessor, Walker, readTertiaryExpr } from '../parsers/walker' @@ -1863,7 +1863,7 @@ function camelComponentBinds (binds) { let ssrIndex = 0 function genSSRId () { - return '_spsrId' + (ssrIndex++) + return 'sspId' + (ssrIndex++) } const stringifier = { @@ -2402,7 +2402,7 @@ const aNodeCompiler = { emitter.writeLine('$slotCtx = $isInserted ? $ctx->owner : $ctx;') if (aNode.vars || aNode.directives.bind) { - emitter.writeLine('$slotCtx = (object)["spsrCid" => $slotCtx->spsrCid, "data" => $slotCtx->data, "instance" => $slotCtx->instance, "owner" => $slotCtx->owner];') + emitter.writeLine('$slotCtx = (object)["sspCid" => $slotCtx->sspCid, "data" => $slotCtx->data, "instance" => $slotCtx->instance, "owner" => $slotCtx->owner];') if (aNode.directives.bind) { emitter.writeLine('_::extend($slotCtx->data, ' + ExpressionEmitter.expr(aNode.directives.bind.value) + ');'); // eslint-disable-line @@ -2642,7 +2642,7 @@ function genComponentContextCode (component, emitter) { emitter.write(Object.keys(component.computed).map(x => `"${x}"`).join(',')) emitter.feedLine('],') - emitter.writeLine(`"spsrCid" => ${component.constructor.spsrCid || 0},`) + emitter.writeLine(`"sspCid" => ${component.constructor.sspCid || 0},`) emitter.writeLine('"sourceSlots" => $sourceSlots,') emitter.writeLine('"data" => $data ? $data : ' + stringifier.any(component.data.get()) + ',') emitter.writeLine('"owner" => $parentCtx,') @@ -2659,12 +2659,15 @@ function genComponentContextCode (component, emitter) { * @param {Function} ComponentClass 组件类 * @return {string} */ -export function compileRenderFunction ({ +export function generateRenderFunction ({ ComponentClass, funcName = '', ns = 'san\\renderer', emitter = new PHPEmitter() }) { + if (typeof ComponentClass !== 'function') { + throw new Error('ComponentClass is needed to generate render function') + } emitter.beginNamespace(ns) emitter.writeLine(`use \\san\\runtime\\_;`) guid = 1 diff --git a/src/compilers/to-php-compiler.ts b/src/compilers/to-php-compiler.ts index e6bb256d..a7db58f3 100644 --- a/src/compilers/to-php-compiler.ts +++ b/src/compilers/to-php-compiler.ts @@ -6,7 +6,7 @@ import { ModuleInfo, generatePHPCode } from '../emitters/generate-php-code' import { transformAstToPHP } from '../transformers/to-php' import { ToJSCompiler } from './to-js-compiler' import { Project } from 'ts-morph' -import { compileRenderFunction } from './php-render-compiler' +import { generateRenderFunction } from './php-render-compiler' import { Compiler } from './compiler' import { PHPEmitter } from '../emitters/php-emitter' import { Component } from '../parsers/component' @@ -36,7 +36,7 @@ export class ToPHPCompiler extends Compiler { super({ fileHeader: ' isReserved(x) ? 'spsrNS' + camelCase(x) : x + const escapeName = x => isReserved(x) ? 'sspNS' + camelCase(x) : x let str = file .slice(this.root.length, -extname(file).length) .split(sep).map(camelCase).map(escapeName).join('\\') diff --git a/src/parsers/component-parser.ts b/src/parsers/component-parser.ts index 2cde5f01..7414e9b7 100644 --- a/src/parsers/component-parser.ts +++ b/src/parsers/component-parser.ts @@ -15,7 +15,7 @@ export class ComponentParser { public project: Project public idPropertyName: string - constructor (project: Project, idPropertyName = 'spsrCid') { + constructor (project: Project, idPropertyName = 'sspCid') { this.project = project this.idPropertyName = idPropertyName } diff --git a/src/parsers/tsconfig.ts b/src/parsers/tsconfig.ts index f978f870..2845bfb9 100644 --- a/src/parsers/tsconfig.ts +++ b/src/parsers/tsconfig.ts @@ -1,9 +1,15 @@ import { cwd } from 'process' import { existsSync } from 'fs' -import { resolve } from 'path' +import { resolve, dirname } from 'path' export function getDefaultConfigPath () { - return resolve(cwd(), 'tsconfig.json') + let dir = cwd() + while (true) { + const filepath = resolve(dir, 'tsconfig.json') + if (existsSync(filepath)) return filepath + if (dirname(dir) === dir) return + dir = dirname(dir) + } } export function getDefaultConfig () { diff --git a/src/transformers/normalize-component.ts b/src/transformers/normalize-component.ts index 15190cc5..ac9c8195 100644 --- a/src/transformers/normalize-component.ts +++ b/src/transformers/normalize-component.ts @@ -2,7 +2,7 @@ import { ClassDeclaration } from 'ts-morph' export function normalizeComponentClass (clazz: ClassDeclaration) { if (!clazz.getName()) { - // clazz.rename('SpsrComponent') // this throws + // clazz.rename('SSPComponent') // this throws throw new Error('anonymous component class is not supported') } diff --git a/src/transformers/to-php.ts b/src/transformers/to-php.ts index b1e58451..d94d2f79 100644 --- a/src/transformers/to-php.ts +++ b/src/transformers/to-php.ts @@ -24,7 +24,7 @@ export function transformAstToPHP (sourceFile: SanSourceFile) { if (clazz.isExported()) { throw new Error(`${name} is a reserved keyword in PHP`) } - clazz.rename(`SpsrClass${name}`) + clazz.rename(`SSPClass${name}`) } } } diff --git a/test/unit/component-parser.spec.ts b/test/unit/component-parser.spec.ts index b318561f..4ed27752 100644 --- a/test/unit/component-parser.spec.ts +++ b/test/unit/component-parser.spec.ts @@ -22,7 +22,7 @@ describe('ComponentParser', function () { expect(result).toContain('class A extends Component') expect(result).toContain('public static template = \'A\'') - expect(result).toContain('static spsrCid: number = 0') + expect(result).toContain('static sspCid: number = 0') }) it('should parse dependency of component class', function () { diff --git a/test/unit/to-js-compiler.spec.ts b/test/unit/to-js-compiler.spec.ts index c0be5779..4bbd4711 100644 --- a/test/unit/to-js-compiler.spec.ts +++ b/test/unit/to-js-compiler.spec.ts @@ -24,7 +24,7 @@ describe('ToJSCompiler', function () { expect(result).toContain('class A extends') expect(result).toContain('A.template = \'A\'') - expect(result).toContain('A.spsrCid = 0') + expect(result).toContain('A.sspCid = 0') }) it('should evalComponentClass', function () { @@ -35,6 +35,6 @@ describe('ToJSCompiler', function () { const componentClass = cc.evalComponentClass(comp) expect(componentClass.template).toEqual('A') - expect(componentClass.spsrCid).toEqual(0) + expect(componentClass.sspCid).toEqual(0) }) })