1 | import * as ts from 'typescript';
|
2 | import * as fs from 'fs-extra';
|
3 | import * as path from 'path';
|
4 | import * as util from 'util';
|
5 |
|
6 | import { logger } from './logger';
|
7 |
|
8 | const carriageReturnLineFeed = '\r\n';
|
9 | const lineFeed = '\n';
|
10 |
|
11 | export function detectIndent(str, count, indent?): string {
|
12 | let stripIndent = function(str: string) {
|
13 | const match = str.match(/^[ \t]*(?=\S)/gm);
|
14 |
|
15 | if (!match) {
|
16 | return str;
|
17 | }
|
18 |
|
19 |
|
20 | const indent = Math.min.apply(Math, match.map(x => x.length));
|
21 | const re = new RegExp(`^[ \\t]{${indent}}`, 'gm');
|
22 |
|
23 | return indent > 0 ? str.replace(re, '') : str;
|
24 | },
|
25 | repeating = function(n, str) {
|
26 | str = str === undefined ? ' ' : str;
|
27 |
|
28 | if (typeof str !== 'string') {
|
29 | throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof str}\``);
|
30 | }
|
31 |
|
32 | if (n < 0 || !Number.isFinite(n)) {
|
33 | throw new TypeError(`Expected \`count\` to be a positive finite number, got \`${n}\``);
|
34 | }
|
35 |
|
36 | let ret = '';
|
37 |
|
38 | do {
|
39 | if (n & 1) {
|
40 | ret += str;
|
41 | }
|
42 |
|
43 | str += str;
|
44 | } while ((n >>= 1));
|
45 |
|
46 | return ret;
|
47 | },
|
48 | indentString = function(str, count, indent) {
|
49 | indent = indent === undefined ? ' ' : indent;
|
50 | count = count === undefined ? 1 : count;
|
51 |
|
52 | if (typeof str !== 'string') {
|
53 | throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof str}\``);
|
54 | }
|
55 |
|
56 | if (typeof count !== 'number') {
|
57 | throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof count}\``);
|
58 | }
|
59 |
|
60 | if (typeof indent !== 'string') {
|
61 | throw new TypeError(`Expected \`indent\` to be a \`string\`, got \`${typeof indent}\``);
|
62 | }
|
63 |
|
64 | if (count === 0) {
|
65 | return str;
|
66 | }
|
67 |
|
68 | indent = count > 1 ? repeating(count, indent) : indent;
|
69 |
|
70 | return str.replace(/^(?!\s*$)/mg, indent);
|
71 | }
|
72 |
|
73 | return indentString(stripIndent(str), count || 0, indent);
|
74 | }
|
75 |
|
76 |
|
77 | export function compilerHost(transpileOptions: any): ts.CompilerHost {
|
78 |
|
79 | const inputFileName = transpileOptions.fileName || (transpileOptions.jsx ? 'module.tsx' : 'module.ts');
|
80 |
|
81 | const compilerHost: ts.CompilerHost = {
|
82 | getSourceFile: (fileName) => {
|
83 | if (fileName.lastIndexOf('.ts') !== -1) {
|
84 | if (fileName === 'lib.d.ts') {
|
85 | return undefined;
|
86 | }
|
87 | if (fileName.substr(-5) === '.d.ts') {
|
88 | return undefined;
|
89 | }
|
90 |
|
91 | if (path.isAbsolute(fileName) === false) {
|
92 | fileName = path.join(transpileOptions.tsconfigDirectory, fileName);
|
93 | }
|
94 | if (!fs.existsSync(fileName)) {
|
95 | return undefined;
|
96 | }
|
97 |
|
98 | let libSource = '';
|
99 |
|
100 | try {
|
101 | libSource = fs.readFileSync(fileName).toString();
|
102 | }
|
103 | catch(e) {
|
104 | logger.debug(e, fileName);
|
105 | }
|
106 |
|
107 | return ts.createSourceFile(fileName, libSource, transpileOptions.target, false);
|
108 | }
|
109 | return undefined;
|
110 | },
|
111 | writeFile: (name, text) => {},
|
112 | getDefaultLibFileName: () => 'lib.d.ts',
|
113 | useCaseSensitiveFileNames: () => false,
|
114 | getCanonicalFileName: fileName => fileName,
|
115 | getCurrentDirectory: () => '',
|
116 | getNewLine: () => '\n',
|
117 | fileExists: (fileName): boolean => fileName === inputFileName,
|
118 | readFile: () => '',
|
119 | directoryExists: () => true,
|
120 | getDirectories: () => []
|
121 | };
|
122 | return compilerHost;
|
123 | }
|