6
6
getSelectedText ,
7
7
getSelectionOffsetRange ,
8
8
importMissingDependencies ,
9
+ workspaceRoot ,
9
10
} from "../editor" ;
10
11
import { getAllTargets } from "../template-parser" ;
11
12
import { showFilePicker } from "../file-picker" ;
@@ -32,26 +33,23 @@ export async function extractToFolder() {
32
33
if ( start && end ) {
33
34
try {
34
35
const text = getSelectedText ( ) || "" ;
35
- const sourceComponentName = await getComponentNameFromHtmlFile (
36
+ const componentText = await getComponentTextFromHtmlFileName (
36
37
activeFileName ( )
37
38
) ;
38
-
39
39
const targets = getAllTargets ( text ) ;
40
+ const sourceComponentConfig = await getCurrentComponentConfig ( componentText ) ;
40
41
41
42
try {
43
+ const rootPath = workspaceRoot ( ) ;
42
44
const folderPath = await showDirectoryPicker ( ) ;
43
- const filePath = ( await showFilePicker ( folderPath ) ) as string ;
44
-
45
- const parts = filePath . split ( "/" ) ;
46
-
47
- const componentName = parts [ parts . length - 1 ] ;
45
+ const fileName = ( await showFilePicker ( ) ) as string ;
48
46
49
- const styleExt = await getStyleExt ( ) ;
47
+ const fullPath = path . join ( rootPath || '' , folderPath , fileName ) ;
50
48
51
- const htmlFilePath = `${ filePath } /${ componentName } .component.html` ;
52
- const cssFilePath = `${ filePath } /${ componentName } .component.${ styleExt } ` ;
53
- const tsFilePath = `${ filePath } /${ componentName } .component.ts` ;
54
- const specFilePath = `${ filePath } /${ componentName } .component.spec.ts` ;
49
+ const htmlFilePath = `${ fullPath } /${ fileName } .component.html` ;
50
+ const cssFilePath = `${ fullPath } /${ fileName } .component.${ sourceComponentConfig . styleExt } ` ;
51
+ const tsFilePath = `${ fullPath } /${ fileName } .component.ts` ;
52
+ const specFilePath = `${ fullPath } /${ fileName } .component.spec.ts` ;
55
53
56
54
await createFileIfDoesntExist ( htmlFilePath ) ;
57
55
await createFileIfDoesntExist ( cssFilePath ) ;
@@ -61,15 +59,15 @@ export async function extractToFolder() {
61
59
await appendSelectedTextToFile ( { text } , htmlFilePath ) ;
62
60
await appendSelectedTextToFile ( { text : `` } , cssFilePath ) ;
63
61
await appendSelectedTextToFile (
64
- { text : getComponentText ( componentName , targets ) } ,
62
+ { text : getComponentText ( fileName , targets , sourceComponentConfig ) } ,
65
63
tsFilePath
66
64
) ;
67
65
await appendSelectedTextToFile (
68
- { text : getSpecText ( componentName ) } ,
66
+ { text : getSpecText ( fileName ) } ,
69
67
specFilePath
70
68
) ;
71
69
72
- const componentInstance = getComponentInstance ( componentName , targets ) ;
70
+ const componentInstance = getComponentInstance ( fileName , targets ) ;
73
71
await persistFileSystemChanges ( replaceSelectionWith ( componentInstance ) ) ;
74
72
75
73
const moduleUris = await vscode . workspace . findFiles (
@@ -83,7 +81,7 @@ export async function extractToFolder() {
83
81
const targetModuleDocuments = moduleDocuments . filter (
84
82
( moduleDocument ) => {
85
83
const allText = moduleDocument . getText ( ) ;
86
- return new RegExp ( `\\b${ sourceComponentName } \\b` ) . test ( allText ) ;
84
+ return new RegExp ( `\\b${ sourceComponentConfig . componentName } \\b` ) . test ( allText ) ;
87
85
}
88
86
) ;
89
87
@@ -99,7 +97,7 @@ export async function extractToFolder() {
99
97
const start = moduleDocument . positionAt ( startOffset ) ;
100
98
const end = moduleDocument . positionAt ( endOffset ) ;
101
99
const targetText = `${ matches [ 0 ] } \n ${ pascalCase (
102
- componentName
100
+ fileName
103
101
) } Component,`;
104
102
105
103
return replaceTextInFile (
@@ -126,23 +124,69 @@ export async function extractToFolder() {
126
124
}
127
125
}
128
126
129
- async function getComponentNameFromHtmlFile ( filePath ) {
127
+ async function getComponentTextFromHtmlFileName ( filePath ) : Promise < string > {
130
128
const name = path . basename ( filePath ) ;
131
129
const dir = path . dirname ( filePath ) ;
132
130
133
131
const tsPath = path . join ( dir , name . replace ( ".html" , ".ts" ) ) ;
134
132
const tsContent = fs . readFileSync ( tsPath , "utf-8" ) ;
135
133
136
- return ( tsContent . match ( / e x p o r t c l a s s \s + ( [ \w _ ] + ) / ) || [ ] ) [ 1 ] ;
134
+ return tsContent ;
137
135
}
138
136
139
- async function getStyleExt ( ) {
137
+ async function getCurrentComponentConfig ( componentText ) {
140
138
try {
141
- const [ angularJsonPath ] = await vscode . workspace . findFiles ( "angular.json" ) ;
142
- const config = JSON . parse ( fs . readFileSync ( angularJsonPath . path , "utf-8" ) ) ;
139
+ const ts = require ( 'typescript' ) ;
140
+ const node = ts . createSourceFile (
141
+ 'x.ts' ,
142
+ componentText ,
143
+ ts . ScriptTarget . Latest // langugeVersion
144
+ ) ;
145
+
146
+ let classDecl ;
147
+ node . forEachChild ( child => {
148
+ if (
149
+ ts . SyntaxKind [ child . kind ] === 'ClassDeclaration' &&
150
+ child . decorators [ 0 ] . expression . expression . escapedText === 'Component'
151
+ ) {
152
+ classDecl = child ;
153
+ }
154
+ } ) ;
155
+ // const decoratorName = classDecl.decorators[0].expression.expression.escapedText;
156
+ const decoratorParams =
157
+ classDecl . decorators [ 0 ] . expression . arguments . reduce ( ( acc , el ) => {
158
+ el . properties . forEach (
159
+ prop => acc [ prop . name . escapedText ] = prop . initializer . elements ? prop . initializer . elements . map ( e => e . text ) : prop . initializer . text
160
+ ) ;
161
+ return acc ;
162
+ } , { } ) ;
163
+
164
+ const styleInline = Boolean ( decoratorParams . style ) ;
165
+
166
+ return {
167
+ componentName : classDecl . name . escapedText ,
168
+ styleInline,
169
+ styleExt : styleInline ? 'css' : trimChar ( path . extname ( decoratorParams . styleUrls [ 0 ] || 'fail.css' ) , '.' )
170
+ } ;
143
171
144
- return config . schematics [ "@schematics/angular:component" ] . styleext ;
145
172
} catch ( e ) {
146
- return "css" ;
173
+
174
+ return {
175
+ componentName : ( componentText . match ( / e x p o r t c l a s s \s + ( [ \w _ ] + ) / ) || [ ] ) [ 1 ] ,
176
+ styleInline : false ,
177
+ styleExt : 'css'
178
+ } ;
179
+
147
180
}
148
181
}
182
+
183
+ function escapeRegExp ( strToEscape ) {
184
+ // Escape special characters for use in a regular expression
185
+ return strToEscape . replace ( / [ \- \[ \] \/ \{ \} \( \) \* \+ \? \. \\ \^ \$ \| ] / g, "\\$&" ) ;
186
+ } ;
187
+
188
+ function trimChar ( origString , charToTrim ) {
189
+ charToTrim = escapeRegExp ( charToTrim ) ;
190
+ var regEx = new RegExp ( "^[" + charToTrim + "]+|[" + charToTrim + "]+$" , "g" ) ;
191
+ return origString . replace ( regEx , "" ) ;
192
+ } ;
0 commit comments