Skip to content

Correct source map url (relative to sourcemap file) #202

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: python
dist: trusty
python:
- pypy
- pypy3
- pypy-5.4.1
- 2.7
- 3.4
- 3.5
Expand Down
21 changes: 13 additions & 8 deletions pysass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,27 +560,32 @@ PySass_compile_filename(PyObject *self, PyObject *args) {
Sass_Output_Style output_style;
int source_comments, error_status, precision;
PyObject *source_map_filename, *custom_functions, *custom_importers,
*result;
*result, *output_filename_hint;

if (!PyArg_ParseTuple(args,
PySass_IF_PY3("yiiyiOOO", "siisiOOO"),
PySass_IF_PY3("yiiyiOOOO", "siisiOOOO"),
&filename, &output_style, &source_comments,
&include_paths, &precision,
&source_map_filename, &custom_functions,
&custom_importers)) {
&custom_importers, &output_filename_hint)) {
return NULL;
}

context = sass_make_file_context(filename);
options = sass_file_context_get_options(context);

if (PyBytes_Check(source_map_filename)) {
size_t source_map_file_len = PyBytes_GET_SIZE(source_map_filename);
if (source_map_file_len) {
char *source_map_file = sass_copy_c_string(
PyBytes_AS_STRING(source_map_filename)
if (PyBytes_GET_SIZE(source_map_filename)) {
sass_option_set_source_map_file(
options, PyBytes_AS_STRING(source_map_filename)
);
}
}
if (PyBytes_Check(output_filename_hint)) {
if (PyBytes_GET_SIZE(output_filename_hint)) {
sass_option_set_output_path(
options, PyBytes_AS_STRING(output_filename_hint)
);
sass_option_set_source_map_file(options, source_map_file);
}
}
sass_option_set_output_style(options, output_style);
Expand Down
53 changes: 28 additions & 25 deletions sass.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ def compile_dirname(
input_filename = input_filename.encode(fs_encoding)
s, v, _ = _sass.compile_filename(
input_filename, output_style, source_comments, include_paths,
precision, None, custom_functions, importers
precision, None, custom_functions, importers, None,
)
if s:
v = v.decode('UTF-8')
Expand Down Expand Up @@ -539,30 +539,32 @@ def my_importer(path):
raise TypeError('source_comments must be bool, not ' +
repr(source_comments))
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
source_map_filename = kwargs.pop('source_map_filename', None)
if not (source_map_filename is None or
isinstance(source_map_filename, string_types)):
raise TypeError('source_map_filename must be a string, not ' +
repr(source_map_filename))
elif isinstance(source_map_filename, text_type):
source_map_filename = source_map_filename.encode(fs_encoding)
if not ('filename' in modes or source_map_filename is None):
raise CompileError('source_map_filename is only available with '
'filename= keyword argument since it has to be '
'aware of it')
try:
include_paths = kwargs.pop('include_paths') or b''
except KeyError:
include_paths = b''
else:
if isinstance(include_paths, collections.Sequence):
include_paths = os.pathsep.join(include_paths)
elif not isinstance(include_paths, string_types):
raise TypeError('include_paths must be a sequence of strings, or '
'a colon-separated (or semicolon-separated if '
'Windows) string, not ' + repr(include_paths))
if isinstance(include_paths, text_type):
include_paths = include_paths.encode(fs_encoding)

def _get_file_arg(key):
ret = kwargs.pop(key, None)
if ret is not None and not isinstance(ret, string_types):
raise TypeError('{} must be a string, not {!r}'.format(key, ret))
elif isinstance(ret, text_type):
ret = ret.encode(fs_encoding)
if ret and 'filename' not in modes:
raise CompileError(
'{} is only available with filename= keyword argument since '
'has to be aware of it'.format(key)
)
return ret

source_map_filename = _get_file_arg('source_map_filename')
output_filename_hint = _get_file_arg('output_filename_hint')

include_paths = kwargs.pop('include_paths', b'') or b''
if isinstance(include_paths, collections.Sequence):
include_paths = os.pathsep.join(include_paths)
elif not isinstance(include_paths, string_types):
raise TypeError('include_paths must be a sequence of strings, or '
'a colon-separated (or semicolon-separated if '
'Windows) string, not ' + repr(include_paths))
if isinstance(include_paths, text_type):
include_paths = include_paths.encode(fs_encoding)

custom_functions = kwargs.pop('custom_functions', ())
if isinstance(custom_functions, collections.Mapping):
Expand Down Expand Up @@ -614,6 +616,7 @@ def my_importer(path):
s, v, source_map = _sass.compile_filename(
filename, output_style, source_comments, include_paths, precision,
source_map_filename, custom_functions, importers,
output_filename_hint,
)
if s:
v = v.decode('utf-8')
Expand Down
1 change: 1 addition & 0 deletions sassc.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ def main(argv=sys.argv, stdout=sys.stdout, stderr=sys.stderr):
output_style=options.style,
source_comments=options.source_comments,
source_map_filename=source_map_filename,
output_filename_hint=args[1],
include_paths=options.include_paths,
precision=options.precision
)
Expand Down
50 changes: 29 additions & 21 deletions sasstests.py
Original file line number Diff line number Diff line change
Expand Up @@ -773,27 +773,6 @@ def test_sassc_source_map_without_css_filename(self):
'actual error message is: ' + repr(err)
assert self.out.getvalue() == ''

def test_sassc_sourcemap(self):
with tempdir() as tmp_dir:
src_dir = os.path.join(tmp_dir, 'test')
shutil.copytree('test', src_dir)
src_filename = os.path.join(src_dir, 'a.scss')
out_filename = os.path.join(tmp_dir, 'a.scss.css')
exit_code = sassc.main(
['sassc', '-m', src_filename, out_filename],
self.out, self.err
)
assert exit_code == 0
assert self.err.getvalue() == ''
assert self.out.getvalue() == ''
with open(out_filename) as f:
assert A_EXPECTED_CSS_WITH_MAP == f.read().strip()
with open(out_filename + '.map') as f:
self.assert_source_map_equal(
dict(A_EXPECTED_MAP, sources=None),
dict(json.load(f), sources=None)
)


@contextlib.contextmanager
def tempdir():
Expand Down Expand Up @@ -1399,3 +1378,32 @@ def test_stack_trace_formatting():
def test_source_comments():
out = sass.compile(string='a{color: red}', source_comments=True)
assert out == '/* line 1, stdin */\na {\n color: red; }\n'


def test_sassc_sourcemap(tmpdir):
src_file = tmpdir.join('src').ensure_dir().join('a.scss')
out_file = tmpdir.join('a.scss.css')
out_map_file = tmpdir.join('a.scss.css.map')

src_file.write('.c { font-size: 5px + 5px; }')

exit_code = sassc.main([
'sassc', '-m', src_file.strpath, out_file.strpath,
])
assert exit_code == 0

contents = out_file.read()
assert contents == (
'.c {\n'
' font-size: 10px; }\n'
'\n'
'/*# sourceMappingURL=a.scss.css.map */'
)
source_map_json = json.loads(out_map_file.read())
assert source_map_json == {
'sources': ['src/a.scss'],
'version': 3,
'names': [],
'file': 'a.scss.css',
'mappings': 'AAAA,AAAA,EAAE,CAAC;EAAE,SAAS,EAAE,IAAS,GAAI',
}