Package com.github.sommeri.less4j.core.output

Source Code of com.github.sommeri.less4j.core.output.SourceMapBuilder

package com.github.sommeri.less4j.core.output;

import java.io.IOException;
import java.util.Collection;

import com.github.sommeri.less4j.LessCompiler;
import com.github.sommeri.less4j.LessSource;
import com.github.sommeri.less4j.LessSource.CannotReadFile;
import com.github.sommeri.less4j.LessSource.FileNotFound;
import com.github.sommeri.less4j.core.parser.HiddenTokenAwareTree;
import com.github.sommeri.less4j.core.problems.BugHappened;
import com.github.sommeri.less4j.utils.URIUtils;
import com.github.sommeri.sourcemap.FilePosition;
import com.github.sommeri.sourcemap.SourceMapFormat;
import com.github.sommeri.sourcemap.SourceMapGenerator;
import com.github.sommeri.sourcemap.SourceMapGeneratorFactory;

/*
   Unused source map v3 features: source content and source root.
*/
public class SourceMapBuilder {

  private final ExtendedStringBuilder cssBuilder;
  private final SourceMapGenerator generator;
  private final LessCompiler.SourceMapConfiguration configuration;
  private final Collection<LessSource> additionalSourceFiles;

  private LessSource cssDestination;

  public SourceMapBuilder(ExtendedStringBuilder cssBuilder, LessSource cssDestination, Collection<LessSource> additionalSourceFiles, LessCompiler.SourceMapConfiguration configuration) {
    this.cssBuilder = cssBuilder;
    this.cssDestination = cssDestination;
    this.configuration = configuration;
    this.additionalSourceFiles = additionalSourceFiles;
    generator = SourceMapGeneratorFactory.getInstance(SourceMapFormat.V3);
  }

  public SourceMapBuilder append(String str, HiddenTokenAwareTree sourceToken) {
    //indentation must be handled before measuring symbol start position
    FilePosition outputStartPosition = beforeSymbolPosition();
    cssBuilder.append(str);
    FilePosition outputEndPosition = afterSymbolPosition();

    createMapping(str, sourceToken, outputStartPosition, outputEndPosition);
    return this;
  }

  public void appendIgnoreNull(String str, HiddenTokenAwareTree sourceToken) {
    FilePosition outputStartPosition = beforeSymbolPosition();
    cssBuilder.append(str);
    FilePosition outputEndPosition = afterSymbolPosition();

    createMapping(str, sourceToken, outputStartPosition, outputEndPosition);
  }

  private void createMapping(String mappedSymbol, HiddenTokenAwareTree sourceToken, FilePosition outputStartPosition, FilePosition outputEndPosition) {
    FilePosition sourceStartPosition = toFilePosition(sourceToken);
    String sourceName = toSourceName(sourceToken);
    String sourceContent = toSourceContent(sourceToken, sourceName);

    generator.addMapping(sourceName, sourceContent, mappedSymbol, sourceStartPosition, outputStartPosition, outputEndPosition);
  }

  private FilePosition beforeSymbolPosition() {
    cssBuilder.handleIndentation();
    FilePosition outputStartPosition = afterSymbolPosition();
    return outputStartPosition;
  }

  private FilePosition afterSymbolPosition() {
    return currentPosition();
  }

  private FilePosition currentPosition() {
    return new FilePosition(cssBuilder.getLine(), cssBuilder.getColumn());
  }

  public void append(SourceMapBuilder other) {
    FilePosition offset = afterSymbolPosition();
    cssBuilder.appendAsIs(other.cssBuilder.toString());
    SourceMapGenerator otherGenerator = other.generator;
    generator.offsetAndAppend(otherGenerator, offset);
  }

  private FilePosition toFilePosition(HiddenTokenAwareTree underlyingStructure) {
    FilePosition result = new FilePosition(underlyingStructure.getLine() - 1, underlyingStructure.getCharPositionInLine());
    return result;
  }

  private String toSourceName(HiddenTokenAwareTree underlyingStructure) {
    LessSource source = underlyingStructure.getSource();
    return toSourceName(source);
  }

  private String toSourceName(LessSource source) {
    if (configuration.isRelativizePaths()) {
      return URIUtils.relativizeSourceURIs(cssDestination, source);
    } else {
      return source.getURI() == null ? null : source.getURI().toString();
    }
  }

  private String toSourceContent(HiddenTokenAwareTree underlyingStructure, String sourceName) {
    LessSource source = underlyingStructure.getSource();
    return toSourceContent(underlyingStructure, sourceName, source);
  }

  private String toSourceContent(HiddenTokenAwareTree underlyingStructure, String sourceName, LessSource source) {
    if (configuration.isIncludeSourcesContent() || sourceName==null) {
      try {
        return source.getContent();
      } catch (FileNotFound e) {
        throw new BugHappened("How did we compiled something we did not read?", underlyingStructure);
      } catch (CannotReadFile e) {
        throw new BugHappened("How did we compiled something we did not read?", underlyingStructure);
      }
    } else {
      return null;
    }
  }

  public String toSourceMap() {
    for (LessSource source : additionalSourceFiles) {
      String sourceName = toSourceName(source);
      String sourceContent = toSourceContent(null, sourceName, source);
      generator.addSourceFile(sourceName, sourceContent);
    }
    // map file is assumed to have the same location as generated css
    String name = "";
    if (cssDestination != null && cssDestination.getName() != null) {
      name = cssDestination.getName();
    }
    try {
      StringBuilder sb = new StringBuilder();
      generator.appendTo(sb, name);
      return sb.toString();
    } catch (IOException e) {
      throw new IllegalStateException("Impossible to happen exception.", e);
    }
  }

  protected ExtendedStringBuilder getCssBuilder() {
    return cssBuilder;
  }

  public void ensureSeparator() {
    cssBuilder.ensureSeparator();
  }

}
TOP

Related Classes of com.github.sommeri.less4j.core.output.SourceMapBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.