|
1 | | -// Used some code from https://github.com/meteor/meteor/blob/devel/packages/coffeescript/plugin/compile-coffeescript.js |
| 1 | +import { Meteor } from 'meteor/meteor'; |
| 2 | +import { CoffeeScriptCompiler } from 'meteor/coffeescript-compiler'; |
2 | 3 |
|
3 | | -global.vue = global.vue || {} |
4 | | -global.vue.lang = global.vue.lang || {} |
| 4 | +const coffeeScriptCompiler = new CoffeeScriptCompiler(); |
5 | 5 |
|
| 6 | +global.vue = global.vue || {}; |
| 7 | +global.vue.lang = global.vue.lang || {}; |
6 | 8 |
|
7 | | -import sourcemap from 'source-map'; |
8 | | -import coffee from 'coffeescript'; |
9 | | -import { |
10 | | - ECMAScript |
11 | | -} from 'meteor/ecmascript'; |
12 | | -import { |
13 | | - Meteor |
14 | | -} from 'meteor/meteor'; |
15 | | - |
16 | | -global.vue.lang.coffee = Meteor.wrapAsync(function({ |
17 | | - source, |
18 | | - inputFile |
19 | | -}, cb) { |
20 | | - |
21 | | - const compileOptions = { |
22 | | - bare: true, |
23 | | - filename: inputFile.getPathInPackage(), |
24 | | - // Return a source map. |
25 | | - sourceMap: true, |
26 | | - // Include the original source in the source map (sourcesContent field). |
27 | | - inline: true, |
28 | | - // This becomes the "file" field of the source map. |
29 | | - generatedFile: "/" + outputFilePath(inputFile), |
30 | | - // This becomes the "sources" field of the source map. |
31 | | - sourceFiles: [inputFile.getDisplayPath()] |
32 | | - }; |
33 | | - |
34 | | - let output = coffee.compile(source, compileOptions); |
35 | | - |
36 | | - try { |
37 | | - output.js = ECMAScript.compileForShell(output.js); |
38 | | - } catch (e) {} |
| 9 | +global.vue.lang.coffee = Meteor.wrapAsync(function({ source, inputFile }, callback) { |
| 10 | + // Override this method so that it returns only the source within the <script> tags. |
| 11 | + inputFile.getContentsAsString = function() { |
| 12 | + return source; |
| 13 | + } |
| 14 | + // Make sure CoffeeScriptCompiler doesn’t think that this is Literate CoffeeScript. |
| 15 | + inputFile.getExtension = function() { |
| 16 | + return 'coffee'; |
| 17 | + } |
39 | 18 |
|
40 | | - const stripped = stripExportedVars( |
41 | | - output.js, |
42 | | - inputFile.getDeclaredExports().map(e => e.name)); |
43 | | - const sourceWithMap = addSharedHeader( |
44 | | - stripped, JSON.parse(output.v3SourceMap)); |
| 19 | + const sourceWithMap = coffeeScriptCompiler.compileOneFile(inputFile); |
45 | 20 |
|
46 | | - cb(null, { |
| 21 | + callback(null, { |
47 | 22 | script: sourceWithMap.source, |
48 | 23 | map: sourceWithMap.sourceMap, |
49 | 24 | useBabel: false |
50 | 25 | }); |
51 | 26 | }); |
52 | | - |
53 | | - |
54 | | -function outputFilePath(inputFile) { |
55 | | - return inputFile.getPathInPackage() + ".js"; |
56 | | -} |
57 | | - |
58 | | -function stripExportedVars(source, exports) { |
59 | | - if (!exports || !exports.length) |
60 | | - return source; |
61 | | - const lines = source.split("\n"); |
62 | | - |
63 | | - for (let i = 0; i < lines.length; i++) { |
64 | | - const line = lines[i]; |
65 | | - const match = /^var (.+)([,;])$/.exec(line); |
66 | | - if (!match) |
67 | | - continue; |
68 | | - |
69 | | - // If there's an assignment on this line, we assume that there are ONLY |
70 | | - // assignments and that the var we are looking for is not declared. (Part |
71 | | - // of our strong assumption about the layout of this code.) |
72 | | - if (match[1].indexOf('=') !== -1) |
73 | | - continue; |
74 | | - |
75 | | - // We want to replace the line with something no shorter, so that all |
76 | | - // records in the source map continue to point at valid |
77 | | - // characters. |
78 | | - function replaceLine(x) { |
79 | | - if (x.length >= lines[i].length) { |
80 | | - lines[i] = x; |
81 | | - } else { |
82 | | - lines[i] = x + new Array(1 + (lines[i].length - x.length)).join(' '); |
83 | | - } |
84 | | - } |
85 | | - |
86 | | - let vars = match[1].split(', ').filter(v => exports.indexOf(v) === -1); |
87 | | - if (vars.length) { |
88 | | - replaceLine("var " + vars.join(', ') + match[2]); |
89 | | - } else { |
90 | | - // We got rid of all the vars on this line. Drop the whole line if this |
91 | | - // didn't continue to the next line, otherwise keep just the 'var '. |
92 | | - if (match[2] === ';') |
93 | | - replaceLine(''); |
94 | | - else |
95 | | - replaceLine('var'); |
96 | | - } |
97 | | - break; |
98 | | - } |
99 | | - |
100 | | - return lines.join('\n'); |
101 | | -} |
102 | | - |
103 | | -function addSharedHeader(source, sourceMap) { |
104 | | - // This ends in a newline to make the source map easier to adjust. |
105 | | - const header = ("__coffeescriptShare = typeof __coffeescriptShare === 'object' " + |
106 | | - "? __coffeescriptShare : {}; " + |
107 | | - "var share = __coffeescriptShare;\n"); |
108 | | - |
109 | | - // If the file begins with "use strict", we need to keep that as the first |
110 | | - // statement. |
111 | | - const processedSource = source.replace(/^(?:((['"])use strict\2;)\n)?/, (match, useStrict) => { |
112 | | - if (match) { |
113 | | - // There's a "use strict"; we keep this as the first statement and insert |
114 | | - // our header at the end of the line that it's on. This doesn't change |
115 | | - // line numbers or the part of the line that previous may have been |
116 | | - // annotated, so we don't need to update the source map. |
117 | | - return useStrict + " " + header; |
118 | | - } else { |
119 | | - // There's no use strict, so we can just add the header at the very |
120 | | - // beginning. This adds a line to the file, so we update the source map to |
121 | | - // add a single un-annotated line to the beginning. |
122 | | - sourceMap.mappings = ";" + sourceMap.mappings; |
123 | | - return header; |
124 | | - } |
125 | | - }); |
126 | | - return { |
127 | | - source: processedSource, |
128 | | - sourceMap: sourceMap |
129 | | - }; |
130 | | -} |
0 commit comments