From 65eabc659f5190d010b6827272f8e855e94ed106 Mon Sep 17 00:00:00 2001 From: void_malex Date: Tue, 1 Oct 2024 21:16:52 +0100 Subject: [PATCH 1/6] add @babel/plugin-syntax-typescript to support parsing ts syntax for template tag codemod --- packages/compat/package.json | 1 + pnpm-lock.yaml | 125 ++++++++++++++++++++--------------- 2 files changed, 74 insertions(+), 52 deletions(-) diff --git a/packages/compat/package.json b/packages/compat/package.json index 795fbb1fe..e46c0ebab 100644 --- a/packages/compat/package.json +++ b/packages/compat/package.json @@ -27,6 +27,7 @@ "@babel/core": "^7.14.5", "@babel/plugin-syntax-decorators": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-typescript": "^7.25.4", "@babel/plugin-transform-runtime": "^7.14.5", "@babel/preset-env": "^7.14.5", "@babel/runtime": "^7.18.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a0c683eca..3a7daae03 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -165,6 +165,9 @@ importers: '@babel/plugin-syntax-dynamic-import': specifier: ^7.8.3 version: 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-typescript': + specifier: ^7.25.4 + version: 7.25.4(@babel/core@7.24.7) '@babel/plugin-transform-runtime': specifier: ^7.14.5 version: 7.24.7(@babel/core@7.24.7) @@ -2294,7 +2297,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-annotate-as-pure': 7.24.7 regexpu-core: 5.3.2 semver: 6.3.1 @@ -2405,6 +2408,11 @@ packages: resolution: {integrity: sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==} engines: {node: '>=6.9.0'} + /@babel/helper-plugin-utils@7.24.8: + resolution: {integrity: sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==} + engines: {node: '>=6.9.0'} + dev: false + /@babel/helper-remap-async-to-generator@7.24.7(@babel/core@7.24.7): resolution: {integrity: sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==} engines: {node: '>=6.9.0'} @@ -2535,7 +2543,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 @@ -2545,7 +2553,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.7(@babel/core@7.24.7): @@ -2581,7 +2589,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 @@ -2630,7 +2638,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 /@babel/plugin-proposal-private-property-in-object@7.21.11(@babel/core@7.24.7): resolution: {integrity: sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==} @@ -2652,7 +2660,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.7): @@ -2669,7 +2677,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.24.7): @@ -2678,7 +2686,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-decorators@7.24.7(@babel/core@7.24.7): @@ -2703,7 +2711,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-import-assertions@7.24.7(@babel/core@7.24.7): @@ -2712,7 +2720,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-import-attributes@7.24.7(@babel/core@7.24.7): @@ -2721,7 +2729,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.7): @@ -2729,7 +2737,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.7): @@ -2737,7 +2745,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.24.7): @@ -2755,7 +2763,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.7): @@ -2763,7 +2771,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.7): @@ -2771,7 +2779,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.7): @@ -2779,7 +2787,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.7): @@ -2787,7 +2795,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.7): @@ -2804,7 +2812,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.7): @@ -2813,7 +2821,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-typescript@7.24.7(@babel/core@7.24.7): @@ -2825,13 +2833,23 @@ packages: '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 + /@babel/plugin-syntax-typescript@7.25.4(@babel/core@7.24.7): + resolution: {integrity: sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.8 + dev: false + /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.24.7): resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) '@babel/helper-plugin-utils': 7.24.7 @@ -2841,7 +2859,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-async-generator-functions@7.24.7(@babel/core@7.24.7): @@ -2906,7 +2924,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-block-scoping@7.24.7(@babel/core@7.24.7): @@ -3013,7 +3031,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 '@babel/template': 7.24.7 @@ -3023,7 +3041,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-dotall-regex@7.24.7(@babel/core@7.24.7): @@ -3032,7 +3050,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) '@babel/helper-plugin-utils': 7.24.7 @@ -3042,7 +3060,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-dynamic-import@7.24.7(@babel/core@7.24.7): @@ -3051,7 +3069,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.7) @@ -3086,7 +3104,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.7) @@ -3121,7 +3139,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-compilation-targets': 7.24.7 '@babel/helper-function-name': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 @@ -3132,7 +3150,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.7) @@ -3142,7 +3160,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-logical-assignment-operators@7.24.7(@babel/core@7.24.7): @@ -3151,7 +3169,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.7) @@ -3161,7 +3179,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-modules-amd@7.24.7(@babel/core@7.24.7): @@ -3276,7 +3294,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) '@babel/helper-plugin-utils': 7.24.7 @@ -3286,7 +3304,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-nullish-coalescing-operator@7.24.7(@babel/core@7.24.7): @@ -3295,7 +3313,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.7) @@ -3305,7 +3323,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.7) @@ -3324,7 +3342,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-compilation-targets': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.7) @@ -3361,7 +3379,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.7) @@ -3461,7 +3479,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-regenerator@7.24.7(@babel/core@7.24.7): @@ -3470,7 +3488,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 regenerator-transform: 0.15.2 @@ -3480,7 +3498,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-runtime@7.24.7(@babel/core@7.24.7): @@ -3505,7 +3523,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-spread@7.24.7(@babel/core@7.24.7): @@ -3539,7 +3557,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-template-literals@7.24.7(@babel/core@7.24.7): @@ -3548,7 +3566,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-typeof-symbol@7.24.7(@babel/core@7.24.7): @@ -3557,7 +3575,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-typescript@7.24.7(@babel/core@7.24.7): @@ -3602,7 +3620,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-unicode-property-regex@7.24.7(@babel/core@7.24.7): @@ -3611,7 +3629,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) '@babel/helper-plugin-utils': 7.24.7 @@ -3621,7 +3639,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) '@babel/helper-plugin-utils': 7.24.7 @@ -3631,7 +3649,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) '@babel/helper-plugin-utils': 7.24.7 @@ -3830,7 +3848,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 dependencies: - '@babel/core': 7.24.7(supports-color@8.1.1) + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 '@babel/types': 7.24.7 esutils: 2.0.3 @@ -8913,6 +8931,9 @@ packages: /ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependenciesMeta: + ajv: + optional: true dependencies: ajv: 8.16.0 From e3fa578844d49a639f7d20a38c70279bb6cb95b5 Mon Sep 17 00:00:00 2001 From: void_malex Date: Tue, 1 Oct 2024 21:20:24 +0100 Subject: [PATCH 2/6] enable ts support fix ambiguous import path replacement use byte positions to insert data in backing class to avoid reformatting code --- packages/compat/src/template-tag-codemod.ts | 146 ++++++++++++-------- 1 file changed, 92 insertions(+), 54 deletions(-) diff --git a/packages/compat/src/template-tag-codemod.ts b/packages/compat/src/template-tag-codemod.ts index 5e3a70476..0b53bc310 100644 --- a/packages/compat/src/template-tag-codemod.ts +++ b/packages/compat/src/template-tag-codemod.ts @@ -1,14 +1,13 @@ import { default as compatBuild } from './default-pipeline'; import type { EmberAppInstance } from '@embroider/core'; import type { Node, InputNode } from 'broccoli-node-api'; -import { join, relative, resolve } from 'path'; +import { join, relative, resolve, extname } from 'path'; import type { types as t } from '@babel/core'; import type { NodePath } from '@babel/traverse'; import { statSync, readdirSync, readFileSync, writeFileSync } from 'fs'; import Plugin from 'broccoli-plugin'; import { transformSync } from '@babel/core'; import { hbsToJS, ResolverLoader } from '@embroider/core'; -import { ImportUtil } from 'babel-import-util'; import ResolverTransform from './resolver-transform'; import { spawn } from 'child_process'; import { locateEmbroiderWorkingDir } from '@embroider/core'; @@ -39,6 +38,10 @@ export default function templateTagCodemod( { shouldTransformPath, dryRun } ); } + +const TEMPLATE_ONLY_MARKER = `import templateOnlyComponent from '@ember/component/template-only';`; +const TEMPLATE_COLOCATION_MARKER = /\/\* import __COLOCATED_TEMPLATE__ from (.*) \*\//; + class TemplateTagCodemodPlugin extends Plugin { constructor(inputNodes: InputNode[], readonly options: TemplateTagCodemodOptions) { super(inputNodes, { @@ -83,12 +86,17 @@ class TemplateTagCodemodPlugin extends Plugin { const babel_plugin_syntax_decorators = require.resolve('@babel/plugin-syntax-decorators', { paths: [embroider_compat_path], }); + const babel_plugin_syntax_typescript = require.resolve('@babel/plugin-syntax-typescript', { + paths: [embroider_compat_path], + }); for await (const current_file of walkSync(tmp_path)) { if (hbs_file_test.test(current_file) && this.options.shouldTransformPath(current_file)) { const template_file_src = readFileSync(current_file).toLocaleString(); - let src = + // run the template transformations using embroider resolver information + // to replace template values with js import syntax used in g(j/t)s + let transformed_source = transformSync(hbsToJS(template_file_src), { plugins: [ [ @@ -102,9 +110,13 @@ class TemplateTagCodemodPlugin extends Plugin { ], filename: current_file, })?.code ?? ''; + + // using transformSync to parse and traverse in one go + // we're only extracting the transformed template information from previous step + // and preserving it for later assembly in the backing class const import_bucket: NodePath[] = []; - let transformed_template_value = ''; - transformSync(src, { + let template_tag_value = ''; + transformSync(transformed_source, { plugins: [ function template_tag_extractor(): unknown { return { @@ -114,11 +126,19 @@ class TemplateTagCodemodPlugin extends Plugin { if (extractor) { const result = resolver.nodeResolve(extractor[0], current_file); if (result.type === 'real') { - // find package + // find package there the resolver is pointing const owner_package = resolver.packageCache.ownerOfFile(result.filename); - // change import to real one - import_declaration.node.source.value = - owner_package!.name + '/' + extractor[1] + '/' + extractor[2]; + let relative_import_path = relative(owner_package!.root, result.filename); + // for addons strip off appPublicationDir from relative path + // we do this on app files as well as they don't contain the + // path that we strip off + // this makes sure that ambiguous imports get properly attributed + relative_import_path = relative_import_path.replace('_app_/', ''); + // remove the extension to match what a developer would normally write + relative_import_path = relative_import_path.slice(0, -extname(relative_import_path).length); + + // change import path to real one + import_declaration.node.source.value = owner_package!.name + '/' + relative_import_path; import_bucket.push(import_declaration); } } else if (import_declaration.node.source.value.indexOf('@ember/template-compilation') === -1) { @@ -134,7 +154,7 @@ class TemplateTagCodemodPlugin extends Plugin { path.node.arguments && 'value' in path.node.arguments[0] ) { - transformed_template_value = ``; + template_tag_value = ``; } }, }, @@ -150,55 +170,40 @@ class TemplateTagCodemodPlugin extends Plugin { ); const backing_class_filename = 'filename' in backing_class_resolution ? backing_class_resolution.filename : ''; + // this can be either a generated js file in case of template only components + // the js or ts file depending on what the app is configured const backing_class_src = readFileSync(backing_class_filename).toString(); - const magic_string = '__MAGIC_STRING_FOR_TEMPLATE_TAG_REPLACE__'; - const is_template_only = - backing_class_src.indexOf("import templateOnlyComponent from '@ember/component/template-only';") !== -1; - src = transformSync(backing_class_src, { + const is_typescript = extname(backing_class_filename) === '.ts'; + + let insert_imports_byte_count = null; + let insert_template_byte_count = null; + + const is_template_only = backing_class_src.indexOf(TEMPLATE_ONLY_MARKER) !== -1; + + // we parse the backing class to find the insert points for imports and template + transformSync(backing_class_src, { plugins: [ - [babel_plugin_syntax_decorators, { decoratorsBeforeExport: true }], - function glimmer_syntax_creator(babel): unknown { + [ + is_typescript ? babel_plugin_syntax_typescript : babel_plugin_syntax_decorators, + { decoratorsBeforeExport: true }, + ], + function glimmer_syntax_creator(/* babel */): unknown { return { name: 'test', visitor: { - Program: { - enter(path: NodePath) { - // Always instantiate the ImportUtil instance at the Program scope - const importUtil = new ImportUtil(babel.types, path); - const first_node = path.get('body')[0]; - if ( - first_node && - first_node.node && - first_node.node.leadingComments && - first_node.node.leadingComments[0]?.value.includes('__COLOCATED_TEMPLATE__') - ) { - //remove magic comment - first_node.node.leadingComments.splice(0, 1); - } - for (const template_import of import_bucket) { - for (let i = 0, len = template_import.node.specifiers.length; i < len; ++i) { - const specifier = template_import.node.specifiers[i]; - if (specifier.type === 'ImportDefaultSpecifier') { - importUtil.import(path, template_import.node.source.value, 'default', specifier.local.name); - } else if (specifier.type === 'ImportSpecifier') { - importUtil.import(path, template_import.node.source.value, specifier.local.name); - } - } - } - }, - }, ImportDeclaration(import_declaration: NodePath) { - if (import_declaration.node.source.value.indexOf('@ember/component/template-only') !== -1) { - import_declaration.remove(); - } + insert_imports_byte_count = import_declaration.node.end; }, ExportDefaultDeclaration(path: NodePath) { + // convention is that we have a default export for each component + // we look for the closing bracket of the class body path.traverse({ ClassBody(path) { - const classbody_nodes = path.get('body'); - //add magic string to be replaces with the contents of the template tag - classbody_nodes[classbody_nodes.length - 1].addComment('trailing', magic_string, false); + // we substract 1 to find the byte right before the final closing bracket `}` + // this is the default insert point for template tag though it could live anywhere inside the class body + // possible future point to add option for putting template first thing in class + insert_template_byte_count = path.node.end ? path.node.end - 1 : 0; }, }); }, @@ -206,23 +211,56 @@ class TemplateTagCodemodPlugin extends Plugin { }; }, ], - })!.code!.replace(`/*${magic_string}*/`, transformed_template_value); + }); + + // list of imports needed by the previous hbs template extracted in second step + const hbs_template_required_imports = import_bucket.join('\n'); + + // we extracted all we needed from transformed_source so we switch to the second phase + // transforming the backing class into what will be our final output + transformed_source = backing_class_src; if (is_template_only) { // because we can't inject a comment as the default export // we replace the known exported string - src = src.replace('templateOnlyComponent()', transformed_template_value); + transformed_source = transformed_source.replace('templateOnlyComponent()', template_tag_value); + // we clean known markers from generated files + transformed_source = transformed_source.replace(TEMPLATE_ONLY_MARKER, hbs_template_required_imports); + transformed_source = transformed_source.replace(TEMPLATE_COLOCATION_MARKER, ''); + } else { + // we modify the source from end to start in order to keep our byte counts valid through the transforms + if (insert_template_byte_count) { + // first we split the backing class at the byte count we found during backing class parsing + // then concat the string back together adding the transformed template in the middle + transformed_source = + transformed_source.substring(0, insert_template_byte_count) + + '\n' + + template_tag_value + + '\n' + + transformed_source.substring(insert_template_byte_count, transformed_source.length); + } + if (insert_imports_byte_count) { + // first we split the backing class at the byte count we found during backing class parsing + // then concat the string back together adding the transformed template in the middle + transformed_source = + transformed_source.substring(0, insert_imports_byte_count) + + '\n' + + hbs_template_required_imports + + '\n' + + transformed_source.substring(insert_imports_byte_count, transformed_source.length); + } + transformed_source = transformed_source.replace(TEMPLATE_COLOCATION_MARKER, ''); } const dryRun = this.options.dryRun ? '--dry-run' : ''; // work out original file path in app tree const app_relative_path = join('app', relative(tmp_path, current_file)); - const new_file_path = app_relative_path.slice(0, -4) + '.gjs'; + const new_file_path = app_relative_path.slice(0, -4) + (is_typescript ? '.gts' : '.gjs'); // write glimmer file out if (this.options.dryRun) { - console.log('Write new file', new_file_path, src); + console.log('Write new file', new_file_path, transformed_source); } else { - writeFileSync(join(process.cwd(), new_file_path), src, { flag: 'wx+' }); + writeFileSync(join(process.cwd(), new_file_path), transformed_source, { flag: 'wx+' }); } // git rm old files (js/ts if exists + hbs) @@ -233,7 +271,7 @@ class TemplateTagCodemodPlugin extends Plugin { if (!is_template_only) { // remove backing class only if it's not a template only component - // resolve repative path to rewritten-app + // resolve relative path to rewritten-app const app_relative_path = join('app', relative(tmp_path, backing_class_filename)); let rm_js = await execute(`git rm ${app_relative_path} ${dryRun}`, { pwd: process.cwd(), From 74d2521250f2ec9c26cf3f47f8245b89c68540ce Mon Sep 17 00:00:00 2001 From: void_malex Date: Tue, 1 Oct 2024 22:04:47 +0100 Subject: [PATCH 3/6] adjust test to match output without babel code transform processing --- tests/scenarios/template-tag-codemod-test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/scenarios/template-tag-codemod-test.ts b/tests/scenarios/template-tag-codemod-test.ts index 2d9a08f7f..1f253d250 100644 --- a/tests/scenarios/template-tag-codemod-test.ts +++ b/tests/scenarios/template-tag-codemod-test.ts @@ -36,7 +36,9 @@ module.exports = function (defaults) { const fileContents = readFileSync(join(app.dir, 'app/components/face.gjs'), 'utf-8'); assert.equal( fileContents, - `export default