def handle_import(self, name, compilation, rule): """Implementation of the core Sass import mechanism, which just looks for files on disk. """ name, ext = os.path.splitext(name) if ext: search_exts = [ext] else: search_exts = ['.scss', '.sass'] dirname, basename = os.path.split(name) # Search relative to the importing file first search_path = [ os.path.normpath(os.path.abspath( os.path.dirname(rule.source_file.path)))] search_path.extend(compilation.compiler.search_path) for prefix, suffix in product(('_', ''), search_exts): filename = prefix + basename + suffix for directory in search_path: path = os.path.normpath( os.path.join(directory, dirname, filename)) if path == rule.source_file.path: # Avoid self-import # TODO is this what ruby does? continue if not os.path.exists(path): continue # Ensure that no one used .. to escape the search path for valid_path in compilation.compiler.search_path: rel = os.path.relpath(path, start=valid_path) if not rel.startswith('../'): break else: continue # All good! return SourceFile.from_filename(path)
def handle_import(self, name, compilation, rule): """Implementation of the core Sass import mechanism, which just looks for files on disk. """ name, ext = os.path.splitext(name) if ext: search_exts = [ext] else: search_exts = ['.scss', '.sass'] dirname, basename = os.path.split(name) # Search relative to the importing file first search_path = [ os.path.normpath(os.path.abspath( os.path.dirname(rule.source_file.path)))] search_path.extend(compilation.compiler.search_path) for prefix, suffix in product(('_', ''), search_exts): filename = prefix + basename + suffix for directory in search_path: path = os.path.normpath( os.path.join(directory, dirname, filename)) if path == rule.source_file.path: # Avoid self-import # TODO is this what ruby does? continue if not os.path.exists(path): continue # Ensure that no one used .. to escape the search path for valid_path in compilation.compiler.search_path: rel = os.path.relpath(path, start=valid_path) if not rel.startswith('../'): break else: continue # All good! return SourceFile.from_filename(path)
def do_build(options, args): if options.output is not None: out = open(options.output, 'wb') else: out = sys.stdout # Get the unencoded stream on Python 3 out = getattr(out, 'buffer', out) css = Scss( scss_opts={ 'style': options.style, 'debug_info': options.debug_info, }, search_paths=options.load_paths, ) if not args: args = ['-'] source_files = [] for path in args: if path == '-': source = SourceFile.from_file(sys.stdin, relpath="<stdin>", is_sass=options.is_sass) else: source = SourceFile.from_filename(path, is_sass=options.is_sass) source_files.append(source) encodings = set(source.encoding for source in source_files) if len(encodings) > 1: sys.stderr.write("Can't combine these files! " "They have different encodings: {0}\n".format( ', '.join(encodings))) sys.exit(3) output = css.compile(source_files=source_files) out.write(output.encode(source_files[0].encoding)) for f, t in profiling.items(): sys.stderr.write("%s took %03fs" % (f, t))
def do_build(options, args): if options.output is not None: out = open(options.output, 'wb') else: out = sys.stdout # Get the unencoded stream on Python 3 out = getattr(out, 'buffer', out) css = Scss(scss_opts={ 'style': options.style, 'debug_info': options.debug_info, }, search_paths=options.load_paths, ) if not args: args = ['-'] source_files = [] for path in args: if path == '-': source = SourceFile.from_file(sys.stdin, relpath="<stdin>", is_sass=options.is_sass) else: source = SourceFile.from_filename(path, is_sass=options.is_sass) source_files.append(source) encodings = set(source.encoding for source in source_files) if len(encodings) > 1: sys.stderr.write( "Can't combine these files! " "They have different encodings: {0}\n" .format(', '.join(encodings)) ) sys.exit(3) output = css.compile(source_files=source_files) out.write(output.encode(source_files[0].encoding)) for f, t in profiling.items(): sys.stderr.write("%s took %03fs" % (f, t))
def compile( self, scss_string=None, scss_file=None, source_files=None, super_selector=None, filename=None, is_sass=None, line_numbers=True): """Compile Sass to CSS. Returns a single CSS string. This method is DEPRECATED; see :mod:`scss.compiler` instead. """ # Derive our root namespace self.scss_vars = _default_scss_vars.copy() if self._scss_vars is not None: self.scss_vars.update(self._scss_vars) root_namespace = Namespace( variables=self.scss_vars, functions=self._library, ) # Figure out search paths. Fall back from provided explicitly to # defined globally to just searching the current directory search_paths = ['.'] if self._search_paths is not None: assert not isinstance(self._search_paths, six.string_types), \ "`search_paths` should be an iterable, not a string" search_paths.extend(self._search_paths) else: if config.LOAD_PATHS: if isinstance(config.LOAD_PATHS, six.string_types): # Back-compat: allow comma-delimited search_paths.extend(config.LOAD_PATHS.split(',')) else: search_paths.extend(config.LOAD_PATHS) search_paths.extend(self._scss_opts.get('load_paths', [])) # Normalize a few old styles of options output_style = self._scss_opts.get('style', config.STYLE) if output_style is True: output_style = 'compressed' elif output_style is False: output_style = 'legacy' # Build the compiler compiler = Compiler( namespace=root_namespace, search_path=search_paths, live_errors=self.live_errors, generate_source_map=self._scss_opts.get('debug_info', False), output_style=output_style, warn_unused_imports=self._scss_opts.get('warn_unused', False), super_selector=super_selector or self.super_selector, ) # Gonna add the source files manually compilation = compiler.make_compilation() # Inject the files we know about # TODO how does this work with the expectation of absoluteness if source_files is not None: for source in source_files: compilation.add_source(source) elif scss_string is not None: source = SourceFile.from_string( scss_string, path=filename, is_sass=is_sass, ) compilation.add_source(source) elif scss_file is not None: source = SourceFile.from_filename( scss_file, path=filename, is_sass=is_sass, ) compilation.add_source(source) # Plus the ones from the constructor if self._scss_files: for name, contents in list(self._scss_files.items()): source = SourceFile.from_string(contents, path=name) compilation.add_source(source) return compiler.call_and_catch_errors(compilation.run)
def compile(self, scss_string=None, scss_file=None, source_files=None, super_selector=None, filename=None, is_sass=None, line_numbers=True): """Compile Sass to CSS. Returns a single CSS string. This method is DEPRECATED; see :mod:`scss.compiler` instead. """ # Derive our root namespace self.scss_vars = _default_scss_vars.copy() if self._scss_vars is not None: self.scss_vars.update(self._scss_vars) root_namespace = Namespace( variables=self.scss_vars, functions=self._library, ) # Figure out search paths. Fall back from provided explicitly to # defined globally to just searching the current directory search_paths = ['.'] if self._search_paths is not None: assert not isinstance(self._search_paths, six.string_types), \ "`search_paths` should be an iterable, not a string" search_paths.extend(self._search_paths) else: if config.LOAD_PATHS: if isinstance(config.LOAD_PATHS, six.string_types): # Back-compat: allow comma-delimited search_paths.extend(config.LOAD_PATHS.split(',')) else: search_paths.extend(config.LOAD_PATHS) search_paths.extend(self._scss_opts.get('load_paths', [])) # Normalize a few old styles of options output_style = self._scss_opts.get('style', config.STYLE) if output_style is True: output_style = 'compressed' elif output_style is False: output_style = 'legacy' # Build the compiler compiler = Compiler( namespace=root_namespace, extensions=[ CoreExtension, ExtraExtension, FontsExtension, CompassExtension, BootstrapExtension, ], search_path=search_paths, live_errors=self.live_errors, generate_source_map=self._scss_opts.get('debug_info', False), output_style=output_style, warn_unused_imports=self._scss_opts.get('warn_unused', False), ignore_parse_errors=config.DEBUG, loops_have_own_scopes=config.CONTROL_SCOPING, undefined_variables_fatal=config.FATAL_UNDEFINED, super_selector=super_selector or self.super_selector, ) # Gonna add the source files manually compilation = compiler.make_compilation() # Inject the files we know about # TODO how does this work with the expectation of absoluteness if source_files is not None: for source in source_files: compilation.add_source(source) elif scss_string is not None: source = SourceFile.from_string( scss_string, path=filename, is_sass=is_sass, ) compilation.add_source(source) elif scss_file is not None: source = SourceFile.from_filename( scss_file, path=filename, is_sass=is_sass, ) compilation.add_source(source) # Plus the ones from the constructor if self._scss_files: for name, contents in list(self._scss_files.items()): source = SourceFile.from_string(contents, path=name) compilation.add_source(source) return compiler.call_and_catch_errors(compilation.run)