-
Notifications
You must be signed in to change notification settings - Fork 0
/
gulpfile.ts
114 lines (107 loc) · 3.63 KB
/
gulpfile.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import pathUtil from 'path';
import gulp from 'gulp';
import modifyFile from 'gulp-modify-file';
import rename from 'gulp-rename';
import ts from 'gulp-typescript';
const tsProject = ts.createProject('tsconfig.json', {
declaration: true,
noEmit: false,
});
const ROOT_DIR = process.cwd() + '/src';
gulp.task('types', () => {
/** 型ファイル出力対象のファイルパス一覧 */
const targetFilePaths = [];
return (
gulp
.src(['./src/components/*.vue', './src/pages/*.vue'], {
base: ROOT_DIR,
})
// scriptブロックだけ抽出する
.pipe(
modifyFile((content, path) => {
const targetFilePath =
'~/' + pathUtil.relative(ROOT_DIR, path.replace('.vue', ''));
{
// tsブロックの場合
const match = content.match(
/<script lang="ts">\n((.|\n)+)<\/script>/
);
if (match) {
const srcTs = match[1];
// importパスの.vueを取り除いてTSとしてimportされるようにする
const replacedSrc = srcTs.replace(/\.vue'/g, `'`);
return replacedSrc;
}
}
{
// setup tsブロックの場合
const match = content.match(
/<script setup lang="ts">\n((.|\n)+)<\/script>/
);
if (match) {
const srcTs = match[1];
// importパスの.vueを取り除いてTSとしてimportされるようにする
const replacedSrc = srcTs.replace(/\.vue'/g, `'`);
const exposeMatch = replacedSrc.match(
/defineExpose\({([^}]+)}\)/
);
const exposeText = exposeMatch ? exposeMatch[1] : '';
return [
`import { defineComponent } from 'vue';`,
replacedSrc,
'export default defineComponent({',
' setup() {',
` return {${exposeText}}`,
' }',
'});',
].join('\n');
}
}
return content;
})
)
// 拡張子を.vue → .tsに変える
.pipe(
rename((path) => {
// パス情報を保存する
targetFilePaths.push('~/' + path.dirname + '/' + path.basename);
path.extname = '.ts';
})
)
// コンパイルをする
.pipe(tsProject())
// 型ファイルの方を操作する
.dts.pipe(
rename((path) => {
// .d.ts → .vue.d.tsにする
path.basename = path.basename.replace(/\.d$/, '.vue.d');
})
)
.pipe(
modifyFile((content, path) => {
// .d.tsを取り除く
const renamedPath = path.replace(/\.d\.ts$/, '');
const relativePath = '~/' + pathUtil.relative(ROOT_DIR, renamedPath);
// コンテンツの内容を書き換える
const replacedContent = (() => {
// declare moduleで括るため、content内のdeclare句は不要になる
let replacedContent = content.replace(/declare/g, '');
// ファイルパスを.vueに戻す
targetFilePaths.forEach((targetFilePath) => {
replacedContent = replacedContent.replace(
new RegExp(targetFilePath),
`${targetFilePath}.vue`
);
});
return replacedContent;
})();
return [
`declare module '${relativePath}' {`,
replacedContent,
'}',
].join('\n');
})
)
.pipe(gulp.dest('src/@types/generate'))
);
});