Skip to content

Commit 8493498

Browse files
committed
Add the implementation of LiveScript
1 parent f3a1690 commit 8493498

File tree

10 files changed

+161
-4
lines changed

10 files changed

+161
-4
lines changed

CHANGES.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Dev
1010
- Add source maps support for CoffeeScript
1111
- Add source maps support for Stylus
1212
- Add source maps support for Babel
13-
13+
- Add the implementation of LiveScript
1414

1515
1.0.1
1616
=====

README.rst

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Django Static Precompiler
33
=========================
44

5-
Django Static Precompiler provides template tags and filters to compile CoffeeScript, SASS / SCSS, LESS, Stylus, and Babel.
5+
Django Static Precompiler provides template tags and filters to compile CoffeeScript, LiveScript, SASS / SCSS, LESS, Stylus, and Babel.
66
It works with both inline code and external files.
77

88
.. image:: https://circleci.com/gh/andreyfedoseev/django-static-precompiler.svg?style=shield
@@ -69,12 +69,14 @@ Example Usage
6969
{% load static %}
7070

7171
<script src="{% static "path/to/script.coffee"|compile %}"></script>
72+
<script src="{% static "path/to/script2.ls"|compile %}"></script>
7273
<link rel="stylesheet" href="{% static "path/to/styles1.less"|compile %}" />
7374
<link rel="stylesheet" href="{% static "path/to/styles2.scss"|compile %}" />
7475

7576
renders to::
7677

7778
<script src="/static/COMPILED/path/to/script.js"></script>
79+
<script src="/static/COMPILED/path/to/script2.js"></script>
7880
<link rel="stylesheet" href="/static/COMPILED/path/to/styles1.css" />
7981
<link rel="stylesheet" href="/static/COMPILED/path/to/styles2.css" />
8082

@@ -90,6 +92,7 @@ Compiler must be specified in ``STATIC_PRECOMPILER_COMPILERS`` setting. Names fo
9092
* ``sass``
9193
* ``scss``
9294
* ``stylus``
95+
* ``livescript``
9396

9497
Example Usage
9598
-------------
@@ -125,6 +128,7 @@ General settings
125128
'static_precompiler.compilers.SCSS',
126129
'static_precompiler.compilers.LESS',
127130
'static_precompiler.compilers.Stylus',
131+
'static_precompiler.compilers.LiveScript',
128132
)
129133

130134
You can specify compiler options using the following format::
@@ -184,6 +188,22 @@ Example::
184188
)
185189

186190

191+
LiveScript
192+
------------
193+
194+
``executable``
195+
Path to LiveScript compiler executable. Default: ``"lsc"``.
196+
197+
``sourcemap_enabled``
198+
Boolean. Set to ``True`` to enable source maps. Default: ``False``
199+
200+
Example::
201+
202+
STATIC_PRECOMPILER_COMPILERS = (
203+
('static_precompiler.compilers.LiveScript', {"executable": "/usr/bin/lsc", "sourcemap_enabled": True}),
204+
)
205+
206+
187207
Babel
188208
-----
189209

circle.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ dependencies:
22
pre:
33
- sudo apt-get install python2.7-dev python3.4-dev
44
- npm install -g [email protected]
5+
- npm install -g [email protected]
56
- npm install -g [email protected]
67
- npm install -g [email protected]
78
- npm install -g [email protected]

provision.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ if [ ! -e /usr/local/bin/node ]; then
1616
fi
1717

1818
sudo npm install -g [email protected]
19+
sudo npm install -g [email protected]
1920
sudo npm install -g [email protected]
2021
sudo npm install -g [email protected]
2122

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def read(fname):
4646
author_email="[email protected]",
4747
url="https://github.com/andreyfedoseev/django-static-precompiler",
4848
description="Django template tags to compile all kinds of static files "
49-
"(SASS, LESS, Stylus, CoffeeScript, Babel).",
49+
"(SASS, LESS, Stylus, CoffeeScript, Babel, LiveScript).",
5050
long_description="\n\n".join([README, CHANGES]),
5151
classifiers=[
5252
'Development Status :: 4 - Beta',
@@ -58,7 +58,7 @@ def read(fname):
5858
'Programming Language :: Python :: 3',
5959
'Topic :: Internet :: WWW/HTTP',
6060
],
61-
keywords=["sass", "scss", "less", "stylus", "css", "coffeescript", "javascript", "babel"],
61+
keywords=["sass", "scss", "less", "stylus", "css", "coffeescript", "javascript", "babel", "livescript"],
6262
tests_require=[
6363
"pytest",
6464
"pytest-django",

static_precompiler/compilers/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
from .scss import * # noqa
55
from .less import * # noqa
66
from .stylus import * # noqa
7+
from .livescript import * # noqa
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import json
2+
import os
3+
import posixpath
4+
5+
from static_precompiler import exceptions, settings, utils
6+
7+
from . import base
8+
9+
__all__ = (
10+
"LiveScript",
11+
)
12+
13+
14+
class LiveScript(base.BaseCompiler):
15+
16+
name = "livescript"
17+
input_extension = "ls"
18+
output_extension = "js"
19+
20+
def __init__(self, executable='lsc', sourcemap_enabled=False):
21+
self.executable = executable
22+
self.is_sourcemap_enabled = sourcemap_enabled
23+
super(LiveScript, self).__init__()
24+
25+
def compile_file(self, source_path):
26+
full_output_path = self.get_full_output_path(source_path)
27+
args = [
28+
self.executable,
29+
"-c",
30+
]
31+
if self.is_sourcemap_enabled:
32+
args.append("-m")
33+
args.append("linked")
34+
args.extend([
35+
"-o", os.path.dirname(full_output_path),
36+
self.get_full_source_path(source_path),
37+
])
38+
out, errors = utils.run_command(args)
39+
40+
if errors:
41+
raise exceptions.StaticCompilationError(errors)
42+
43+
if self.is_sourcemap_enabled:
44+
# Livescript writes source maps to compiled.map, not compiled.js.map
45+
sourcemap_full_path = full_output_path + ".map"
46+
47+
with open(sourcemap_full_path) as sourcemap_file:
48+
sourcemap = json.loads(sourcemap_file.read())
49+
50+
# LiveScript, unlike SASS, can't add correct relative paths in source map when the compiled file
51+
# is not in the same dir as the source file. We fix it here.
52+
sourcemap["sourceRoot"] = "../" * len(source_path.split("/")) + posixpath.dirname(source_path)
53+
sourcemap["sources"] = [os.path.basename(source) for source in sourcemap["sources"]]
54+
sourcemap["file"] = posixpath.basename(os.path.basename(full_output_path))
55+
56+
with open(sourcemap_full_path, "w") as sourcemap_file:
57+
sourcemap_file.write(json.dumps(sourcemap))
58+
59+
return self.get_output_path(source_path)
60+
61+
def compile_source(self, source):
62+
args = [
63+
self.executable,
64+
"-c",
65+
"-s",
66+
"-p",
67+
]
68+
out, errors = utils.run_command(args, source)
69+
if errors:
70+
raise exceptions.StaticCompilationError(errors)
71+
72+
return out
73+
74+
def find_dependencies(self, source_path):
75+
return []

static_precompiler/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"static_precompiler.compilers.SCSS",
1919
"static_precompiler.compilers.LESS",
2020
"static_precompiler.compilers.Stylus",
21+
"static_precompiler.compilers.LiveScript",
2122
))
2223

2324
ROOT = getattr(settings, "STATIC_PRECOMPILER_ROOT",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log "Hello, World!"
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# coding: utf-8
2+
import os
3+
4+
import pytest
5+
6+
from static_precompiler import compilers, exceptions
7+
8+
9+
def clean_javascript(js):
10+
""" Remove comments and all blank lines. """
11+
return "\n".join(
12+
line for line in js.split("\n") if line.strip() and not line.startswith("//")
13+
)
14+
15+
16+
def test_compile_file(monkeypatch, tmpdir):
17+
monkeypatch.setattr("static_precompiler.settings.ROOT", tmpdir.strpath)
18+
19+
compiler = compilers.LiveScript()
20+
21+
assert clean_javascript(compiler.compile_file("scripts/test.ls")) == "COMPILED/scripts/test.js"
22+
assert os.path.exists(compiler.get_full_output_path("scripts/test.ls"))
23+
with open(compiler.get_full_output_path("scripts/test.ls")) as compiled:
24+
assert clean_javascript(compiled.read()) == """(function(){\n console.log("Hello, World!");\n}).call(this);"""
25+
26+
27+
def test_sourcemap(monkeypatch, tmpdir):
28+
29+
monkeypatch.setattr("static_precompiler.settings.ROOT", tmpdir.strpath)
30+
31+
compiler = compilers.LiveScript(sourcemap_enabled=False)
32+
compiler.compile_file("scripts/test.ls")
33+
full_output_path = compiler.get_full_output_path("scripts/test.ls")
34+
assert not os.path.exists(full_output_path + ".map")
35+
36+
compiler = compilers.LiveScript(sourcemap_enabled=True)
37+
compiler.compile_file("scripts/test.ls")
38+
full_output_path = compiler.get_full_output_path("scripts/test.ls")
39+
assert os.path.exists(full_output_path + ".map")
40+
41+
42+
def test_compile_source():
43+
compiler = compilers.LiveScript()
44+
45+
assert (
46+
clean_javascript(compiler.compile_source('console.log "Hello, World!"')) ==
47+
"""(function(){\n console.log("Hello, World!");\n}).call(this);"""
48+
)
49+
50+
with pytest.raises(exceptions.StaticCompilationError):
51+
compiler.compile_source('console.log "Hello, World!')
52+
53+
# Test non-ascii
54+
assert (
55+
clean_javascript(compiler.compile_source('console.log "Привет, Мир!"')) ==
56+
"""(function(){\n console.log("Привет, Мир!");\n}).call(this);"""
57+
)

0 commit comments

Comments
 (0)