Skip to content

Commit 7ef3d57

Browse files
author
Andrey Fedoseev
committed
Add source maps support for CoffeeScript
1 parent 0dc3eda commit 7ef3d57

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

CHANGES.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Dev
77

88
- Add source maps support for SASS/SCSS
99
- Add source maps support for LESS
10+
- Add source maps support for CoffeeScript
1011

1112

1213
1.0.1

README.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,13 @@ CoffeeScript
174174
``executable``
175175
Path to CoffeeScript compiler executable. Default: ``"coffee"``.
176176

177+
``sourcemap_enabled``
178+
Boolean. Set to ``True`` to enable source maps. Default: ``False``
179+
177180
Example::
178181

179182
STATIC_PRECOMPILER_COMPILERS = (
180-
('static_precompiler.compilers.CoffeeScript', {"executable": "/usr/bin/coffee"}),
183+
('static_precompiler.compilers.CoffeeScript', {"executable": "/usr/bin/coffee", "sourcemap_enabled": True}),
181184
)
182185

183186

static_precompiler/compilers/coffeescript.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import json
12
import os
3+
import posixpath
24

35
from static_precompiler import exceptions, settings, utils
46

@@ -15,20 +17,44 @@ class CoffeeScript(base.BaseCompiler):
1517
input_extension = "coffee"
1618
output_extension = "js"
1719

18-
def __init__(self, executable=settings.COFFEESCRIPT_EXECUTABLE):
20+
def __init__(self, executable=settings.COFFEESCRIPT_EXECUTABLE, sourcemap_enabled=False):
1921
self.executable = executable
22+
self.is_sourcemap_enabled = sourcemap_enabled
2023
super(CoffeeScript, self).__init__()
2124

2225
def compile_file(self, source_path):
26+
full_output_path = self.get_full_output_path(source_path)
2327
args = [
2428
self.executable,
2529
"-c",
26-
"-o", os.path.dirname(self.get_full_output_path(source_path)),
27-
self.get_full_source_path(source_path),
2830
]
31+
if self.is_sourcemap_enabled:
32+
args.append("-m")
33+
args.extend([
34+
"-o", os.path.dirname(full_output_path),
35+
self.get_full_source_path(source_path),
36+
])
2937
out, errors = utils.run_command(args)
38+
3039
if errors:
3140
raise exceptions.StaticCompilationError(errors)
41+
42+
if self.is_sourcemap_enabled:
43+
# Coffeescript writes source maps to compiled.map, not compiled.js.map
44+
sourcemap_full_path = os.path.splitext(full_output_path)[0] + ".map"
45+
46+
with open(sourcemap_full_path) as sourcemap_file:
47+
sourcemap = json.loads(sourcemap_file.read())
48+
49+
# CoffeeScript, unlike SASS, can't add correct relative paths in source map when the compiled file
50+
# is not in the same dir as the source file. We fix it here.
51+
sourcemap["sourceRoot"] = "../" * len(source_path.split("/")) + posixpath.dirname(source_path)
52+
sourcemap["sources"] = [os.path.basename(source) for source in sourcemap["sources"]]
53+
sourcemap["file"] = posixpath.basename(os.path.basename(full_output_path))
54+
55+
with open(sourcemap_full_path, "w") as sourcemap_file:
56+
sourcemap_file.write(json.dumps(sourcemap))
57+
3258
return self.get_output_path(source_path)
3359

3460
def compile_source(self, source):

static_precompiler/tests/test_coffeescript.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,21 @@ def test_compile_file(monkeypatch, tmpdir):
2424
assert clean_javascript(compiled.read()) == """(function() {\n console.log("Hello, World!");\n}).call(this);"""
2525

2626

27+
def test_sourcemap(monkeypatch, tmpdir):
28+
29+
monkeypatch.setattr("static_precompiler.settings.ROOT", tmpdir.strpath)
30+
31+
compiler = compilers.CoffeeScript(sourcemap_enabled=False)
32+
compiler.compile_file("scripts/test.coffee") == "COMPILED/scripts/test.js"
33+
full_output_path = compiler.get_full_output_path("scripts/test.coffee")
34+
assert not os.path.exists(os.path.splitext(full_output_path)[0] + ".map")
35+
36+
compiler = compilers.CoffeeScript(sourcemap_enabled=True)
37+
compiler.compile_file("scripts/test.coffee") == "COMPILED/scripts/test.js"
38+
full_output_path = compiler.get_full_output_path("scripts/test.coffee")
39+
assert os.path.exists(os.path.splitext(full_output_path)[0] + ".map")
40+
41+
2742
def test_compile_source():
2843
compiler = compilers.CoffeeScript()
2944

0 commit comments

Comments
 (0)