Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
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))
Ejemplo n.º 4
0
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))
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
    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)