/** * Read an object path and optionally filter some child paths. * * @param path Path to read. * @param without Properties to filter. * @return Properties. */ private Map<String, Object> attrs(final String path, final String... without) { Map<String, Object> attrs = new LinkedHashMap<>(get(path)); Arrays.asList(without).forEach(attrs::remove); return attrs; }
/** * Parse a css size unit value, like 10px or 18.919px and optionally round the value to the * closest integer. * * @param value Value to parse. * @return A tuple with a number and unit(px, em, etc...) */ private Tuple<Number, String> parse(final String value) { Matcher matcher = SIZE.matcher(value); if (matcher.find()) { String number = matcher.group(1); String unit = matcher.group(_3); boolean round = get("css.round"); Number num = Double.parseDouble(number); return new Tuple(round ? Math.round(num.doubleValue()) : num, unit); } return null; }
/** * Generate a CSS rule, it reads the width and height attributes of the svg element or fallback to * viewBox attribute. * * @param id ID to use. * @param svg Svg element to convert. * @return A css rule. */ private CharSequence css(final String id, final Element svg) { Throwing.Function<String, Tuple<Tuple<Number, String>, Tuple<Number, String>>> viewBox = Throwing .<String, Tuple<Tuple<Number, String>, Tuple<Number, String>>>throwingFunction(name -> { String vbox = svg.attr(name); String[] dimension = vbox.split("\\s+"); return new Tuple(parse(dimension[2]), parse(dimension[_3])); }).memoized(); Tuple<Number, String> w = Optional.ofNullable(Strings.emptyToNull(svg.attr("width"))) .map(this::parse) .orElseGet(() -> viewBox.apply("viewBox")._1); Tuple<Number, String> h = Optional.ofNullable(Strings.emptyToNull(svg.attr("height"))) .map(this::parse) .orElseGet(() -> viewBox.apply("viewBox")._2); StringBuilder css = new StringBuilder(); css.append(get("css.prefix").toString()).append(".").append(id) .append(" {\n width: ").append(w._1).append(w._2).append(";\n") .append(" height: ").append(h._1).append(h._2).append(";\n}"); return css; }
@Override public void run(final Config conf) throws Exception { String input = get("input"); if (input == null) { throw new IllegalArgumentException("Required option 'svg-symbol.input' not present"); } Path basedir = Paths.get(get("basedir").toString()); Path dir = basedir.resolve(input); List<CharSequence> cssout = new ArrayList<>(); Element svg = new Element(Tag.valueOf("svg"), ""); attrs("svg", "output").forEach((n, v) -> svg.attr(n, v.toString())); files(dir, file -> { log.debug("{}", file); String id = get("id.prefix") + file.getFileName().toString().replace(".svg", "") + get("id.suffix"); Tuple<Element, Element> rewrite = symbol(file, id); svg.appendChild(rewrite._2); cssout.add(css(id, rewrite._1)); }); write(basedir.resolve(svgPath()), ImmutableList.of(svg.outerHtml())); write(basedir.resolve(cssPath()), cssout); }