GithubHelp home page GithubHelp logo

phax / ph-css Goto Github PK

View Code? Open in Web Editor NEW
153.0 12.0 22.0 5.52 MB

Advanced Java CSS 3 parser and builder

License: Apache License 2.0

CSS 42.83% Java 49.70% HTML 7.47%
java java8 css parse css3 modify write css-parser

ph-css's Introduction

ph-css

Maven Central javadoc CodeCov

Java CSS 2 and CSS 3 parser and builder. This version supersedes phloc-css. The Maven plugin to compress CSS files at build time is located in sub-project ph-csscompress-maven-plugin and described further down.

ph-css has no logic for applying CSS onto HTML elements. This page shows some basic code examples that can be used to use the library. All snippets are free for any use.

ph-css and ph-csscompress-maven-plugin are both licensed under the Apache 2.0 license.

ph-css is used as a part of Apache JMeter 3 :)

Maven usage

Add the following to your pom.xml to use this artifact, replacing x.y.z with the latest version:

<dependency>
  <groupId>com.helger</groupId>
  <artifactId>ph-css</artifactId>
  <version>x.y.z</version>
</dependency>

To build ph-css from source, Maven 3.0.4 is required. Any Maven version below does NOT work!

Documentation

As ph-css is mainly concerned about the grammatical structure of CSS, the main classes are for reading and writing CSS. Additionally it offers the possibility to traverse the elements in a CSS and make modifications on them.

Coding paradigms used

Please look at my personal Coding Styleguide for the naming conventions used in this project.

Basic Classes

A complete stylesheet is represented as an instance of com.helger.css.decl.CascadingStyleSheet. There is no difference between CSS 2.1 and CSS 3.0 instances. The class com.helger.css.decl.CascadingStyleSheet contains all top-level rules that may be present in a CSS:

  • Import rules (@import) - com.helger.css.decl.CSSImportRule
  • Namespace rules (@namespace) - com.helger.css.decl.CSSNamespaceRule
  • Style rules (e.g. div{color:red;}) - com.helger.css.decl.CSSStyleRule
  • Page rules (@page) - com.helger.css.decl.CSSPageRule
  • Media rules (@media) - com.helger.css.decl.CSSMediaRule
  • Font face rules (@font-face) - com.helger.css.decl.CSSFontFaceRule
  • Keyframes rules (@keyframes) - com.helger.css.decl.CSSKeyframesRule
  • Viewport rules (@viewport) - com.helger.css.decl.CSSViewportRule
  • Supports rules (@supports) - com.helger.css.decl.CSSSupportsRule
  • Any other unknown rules (@foo) - com.helger.css.decl.CSSUnknownRule

CSS reading

ph-css contains two different possibilities to read CSS data:

  • Reading a complete CSS file can be achieved using com.helger.css.reader.CSSReader. The result in this case will be an instance of com.helger.css.decl.CascadingStyleSheet.
  • Reading only a list of style information (as e.g. present in an HTML style element) can be achieved using com.helger.css.reader.CSSReaderDeclarationList. The result in this case will be an instance of com.helger.css.decl.CSSDeclarationList.

Both reading classes support the reading from either a java.io.File, a java.io.Reader, a com.helger.commons.io.IInputStreamProvider or a String. The reason why java.io.InputStream is not supported directly is because internally the stream is passed twice - first to determine a potentially available charset and second to read the content with the correctly determined charset. That's why an IInputStreamProvider must be used, that creates 2 unique input streams!

Note: reading from a String is possible in two different ways: one that requires a charset and one that doesn't. The version with the charset treats the String as if it was created from a byte array and tries to determine the charset like any other byte array based version. The version without a charset assumes that the String was already created with the correct charset, and any @charset rule contained in the CSS is ignored.

Since v3.8.2 the class com.helger.css.reader.CSSReaderSettings is present and encapsulates the CSS version, the fallback charset, the recoverable error handler (see below) and the unrecoverable error handler (also see below) in one settings object. This settings object can be used for multiple invocations of CSSReader and CSSReaderDeclarationList.

Recoverable Errors

ph-css differentiates between recoverable errors and unrecoverable errors. An example for a recoverable error is e.g. an @import rule in the wrong place or a missing closing bracket within a style declaration. For recoverable errors a special handler interface com.helger.css.reader.errorhandler.ICSSParseErrorHandler is present. You can pass an implementation of this error handler to the CSS reader (see above). The following implementations are present by default (all residing in package com.helger.css.reader.errorhandler):

  • DoNothingCSSParseErrorHandler - silently ignoring all recoverable errors
  • LoggingCSSParseErrorHandler - logging all recoverable errors to an SLF4J logger
  • ThrowingCSSParseErrorHandler - throws a com.helger.css.parser.ParseException in case of a recoverable error which is afterwards handled by the unrecoverable error handler (see below). This can be used to enforce handling only 100% valid CSS files. This is the default setting, if no error handler is specified during reading.
  • CollectingCSSParseErrorHandler - collects all recoverable errors into a list of com.helger.css.reader.errorhandler.CSSParseError instances for later evaluation.

Some error handlers can be nested so that a combination of a logging handler and a collecting handler can easily be achieved like:

new CollectingCSSParseErrorHandler (new LoggingCSSParseErrorHandler ())

DoNothingCSSParseErrorHandler and ThrowingCSSParseErrorHandler cannot be nested because it makes no sense.

Both CSSReader and CSSReaderDeclarationList have the possibility to define a default recoverable error handler using the method setDefaultParseErrorHandler(ICSSParseErrorHandler). If a reading method is invoked without an explicit ICSSParseErrorHandler than this default error handler is used.

Unrecoverable Errors

In case of an unrecoverable error, the underlying parser engine of JavaCC throws a com.helger.css.parser.ParseException. This exception contains all the necessary information on where the error occurred. In case of such an unrecoverable error, the result of the reading will always be null and the exception is not automatically propagated to the caller. To explicitly get notified when such a parse error occurs, the handler interface com.helger.css.handler.ICSSParseExceptionCallback is available. The available implementations are (all residing in package com.helger.css.handler):

  • DoNothingCSSParseExceptionHandler - silently ignore all unrecoverable errors
  • LoggingCSSParseExceptionHandler - log all unrecoverable errors to an SLF4J logger

As there is at most one unrecoverable error per parse there is no collecting implementation of an ICSSParseExceptionCallback available. If it is desired to propagate the Exception to the caller you need to implement your own ICSSParseExceptionCallback subclass that throws an unchecked exception (one derived from RuntimeException). Example:

  final ICSSParseExceptionCallback aThrowingExceptionHandler = new ICSSParseExceptionCallback () {
    public void onException (final ParseException ex) {
      throw new IllegalStateException ("Failed to parse CSS", ex);
    }
  };

Both CSSReader and CSSReaderDeclarationList have the possibility to define a default unrecoverable error handler using the method setDefaultParseExceptionHandler(ICSSParseExceptionCallback). If a reading method is invoked without an explicit ICSSParseExceptionCallback than this default exception handler is used.

CSS iteration/visiting

Once a CSS file was successfully read, it can easily be iterated using the class com.helger.css.decl.visit.CSSVisitor. It requires a valid instance of com.helger.css.decl.CascadingStyleSheet as well as an implementation of com.helger.css.decl.visit.ICSSVisitor. The CascadingStyleSheet can be acquired either by reading from a file/stream or by creating a new one from scratch. For the ICSSVisitor it is recommended to use the class com.helger.css.decl.visit.DefaultCSSVisitor as the base class - this class contains empty implementations of all methods defined in the ICSSVisitor interface. To visit all declarations (e.g. color:red;) it is sufficient to simply override the method public void onDeclaration (@Nonnull final CSSDeclaration aDeclaration). For details please have a look at the JavaDocs of ICSSVisitor. To start the visiting call CSSVisitor.visitCSS (CascadingStyleSheet, ICSSVisitor).

A special visitor is present for URLs. URLs can occur on several places in CSS files, especially in the @import rules and within declarations (like in background-image: url(../images/bg.gif)). Therefore a special interface com.helger.css.decl.visit.ICSSUrlVisitor together with the empty default implementation com.helger.css.decl.visit.DefaultCSSUrlVisitor is provided. So to visit all URLs within a CSS call CSSVisitor.visitCSSUrl(CascadingStyleSheet, ICSSUrlVisitor). Since v6.2.3 the URL visitor recursively descends into expression members (see issue #59).

For modifying URLs (e.g. to adopt paths to a different environment) a special base class com.helger.css.decl.visit.AbstractModifyingCSSUrlVisitor is available. It offers the abstract method protected abstract String getModifiedURI (@Nonnull String sURI) to modify a URL and write the result back into the original CascadingStyleSheet. An example of how this can be used, can be found in the test method com.helger.css.decl.visit.CSSVisitorDeclarationListTest.testModifyingCSSUrlVisitor ().

Note: it is safe to modify a CSS while iterating it, but only changes affecting children of the current node may be considered during the same iteration run.

CSS writing

CSS writing is performed with the class com.helger.css.writer.CSSWriter. The most basic settings can be passed either directly to the constructor or using an instance of com.helger.css.writer.CSSWriterSettings which offers a quite find grained control of the output process. To write the content of a CascadingStyleSheet or any ICSSWriteable to an arbitrary java.io.Writer, the method writeCSS is what you need. If you want the CSS serialized to a String the shortcut method getCSSAsString is available. For the remaining configuration methods please check the JavaDoc.

By default all CSS code is pretty-printed. To create a minified version of the CSS code call setOptimizedOutput (true) and setRemoveUnnecessaryCode (true) on your CSSWriterSettings object.

Data URL handling

Data URLs are URLs that directly contain the content inline. A regular use case is referencing small images directly inside a CSS. During CSS parsing no special handling for data URLs is added. Instead they are stored in a String like any other URL.

To special handle data URLs the class com.helger.css.utils.CSSDataURLHelper offers the possibility to check if a URL is a data URL via public static boolean isDataURL (String). If this method returns true the method public static CSSDataURL parseDataURL (String) can be used to extract all the information contained in the data URL. This method returns null if the passed URL is not a data URL.

Shorthand property handling

A CSS shorthand property is a property that consists of multiple values. Classical examples are margin or border. ph-css contains support for selected shorthand properties. All shorthand related classes can be found in package com.helger.css.decl.shorthand. The supported shorthand properties are:

  • background
  • font
  • border
  • border-top
  • border-right
  • border-bottom
  • border-left
  • border-width
  • border-style
  • border-color
  • margin
  • padding
  • outline
  • list-style

All of these shorthand properties are registered in class CSSShortHandRegistry and you can manually register your own shorthand descriptors. The CSSShortHandRegistry allows you to split a single CSSDeclaration like border:1px dashed into the corresponding "sub-declarations":

  // Parse a dummy declaration
  final CSSDeclaration aDecl = CSSReaderDeclarationList.readFromString ("border:1px dashed", ECSSVersion.CSS30).getDeclarationAtIndex (0);

  // Get the Shorthand descriptor for "border"    
  final CSSShortHandDescriptor aSHD = CSSShortHandRegistry.getShortHandDescriptor (ECSSProperty.BORDER);

  // And now split it into pieces
  final List <CSSDeclaration> aSplittedDecls = aSHD.getSplitIntoPieces (aDecl);

In the above example, aSplittedDecls will contain 3 elements with the following content:

  • border-width:1px
  • border-style:dashed
  • border-color:black

Even though no color value was provided, the default value black is returned. For all "sub-declarations", sensible default values are defined.

CSS utilities

ph-css contains a multitude of small utility class covering different aspects of CSS

  • com.helger.css.utils.CSSColorHelper contains methods to read and write the different types of CSS color values (rgb, rgba, hsl, hsla and hex value)
  • com.helger.css.utils.ECSSColor contains the basic CSS colors as an enumeration
  • com.helger.css.ECSSUnit contains all the default CSS units (like. px or em)
  • com.helger.css.utils.CSSNumberHelper contains methods for handling the combination of numeric values and units.
  • com.helger.css.utils.CSSRectHelper contains methods for handling CSS rect values.
  • com.helger.css.tools.MediaQueryTools provides shortcut methods for wrapping a complete CascadingStyleSheet in one or more media queries

Code Examples

  • Reading a CSS 3.0 file
  • Writing a CSS 3.0 file
  • Creating a @font-face rule from scratch
  • The code creates a CSS @font-face rule that looks like this:
    @font-face {
      font-family: "Your typeface";
      src: url("path/basename.eot");
      src: local("local font name"),
           url("path/basename.woff") format("woff"),
           url("path/basename.otf") format("opentype"),
           url("path/basename.svg#filename") format("svg");
    }
  • Read the CSS content of a HTML style attribute
    • Reads the CSS content of sStyle as CSS 3.0 and creates a CSSDeclarationList from it
  • Visiting all declarations contained in an HTML style attribute
    • Similar to the above example, but visiting all declarations and printing them on stdout. Two different approaches are shown: first all declarations are retrieved via the native API, and second a custom visitor is used to determine all declarations. The result of this method looks like this:
    color: red (not important)
    background: fixed (important)
    
  • Visit all URLs contained in a CSS
    • Read a CSS from a String and than extracts all contained URLs. The output looks like this:
    Import: foobar.css - source location reaches from [1/1] up to [1/21]
    background - references: a.gif - source location reaches from [2/22] up to [2/31]
    background-image - references: /my/folder/b.gif - source location reaches from [3/25] up to [3/47]
    
  • Visit all URLs (incl.data URLs) contained in a CSS
    • Read a CSS from a String and than extracts all contained URLs with special focus on data URLs. The output looks like this:
    Import: /folder/foobar.css
    background - references data URL with 158 bytes of content
    background-image - references regular URL: /my/folder/b.gif
    

Known shortcomings

The following list gives an overview of known shortcomings in ph-css

  • Escaped characters (like \26) are not interpreted correctly.

ph-csscompress-maven-plugin

A Maven plugin to compress CSS files at build time using ph-css.

It requires Java 8 and Maven 3 to run.

Maven configuration

Replace x.y.z with the version you want to use.

      <plugin>
        <groupId>com.helger.maven</groupId>
        <artifactId>ph-csscompress-maven-plugin</artifactId>
        <version>x.y.z</version>
        <executions>
          <execution>
            <goals>
              <goal>csscompress</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <forceCompress>false</forceCompress>
          <removeUnnecessaryCode>true</removeUnnecessaryCode>
          <quoteURLs>true</quoteURLs>
          <verbose>true</verbose>
          <sourceDirectory>${basedir}/src/main/resources</sourceDirectory>
        </configuration>
      </plugin>

Configuration items are:

  • File sourceDirectory
    The directory where the CSS files reside. It must be an existing directory.
    Defaults to ${basedir}/src/main/resources
  • boolean recursive
    Should all directories be scanned recursively for CSS files to compress? Defaults to true
  • boolean removeUnnecessaryCode
    Should unnecessary code be removed (e.g. rules without declarations)? Defaults to false
  • boolean quoteURLs
    Should URLs always be quoted? If false they are only quoted when absolutely necessary. Defaults to false
  • boolean writeNamespaceRules
    Should @namespace rules be written? Defaults to true
  • boolean writeFontFaceRules
    Should @font-face rules be written? Defaults to true
  • boolean writeKeyframesRules
    Should @keyframes rules be written? Defaults to true
  • boolean writeMediaRules
    Should @media rules be written? Defaults to true
  • boolean writePageRules
    Should @page rules be written? Defaults to true
  • boolean writeViewportRules
    Should @viewport rules be written? Defaults to true
  • boolean writeSupportsRules
    Should @supports rules be written? Defaults to true
  • boolean writeUnknownRules
    Should unknown @ rules be written? Defaults to true
  • boolean forceCompress
    Should the CSS files be compressed, even if the timestamp of the compressed file is newer than the timestamp of the original CSS file? Defaults to false
  • boolean verbose
    If true some more output is emitted. Defaults to false
  • boolean browserCompliantMode (since 1.4.0) If true the "browser compliant mode" for parsing is selected. Defaults to false.
  • String sourceEncoding
    The encoding of the source CSS files to be used for reading the CSS file in case neither a @charset rule nor a BOM is present. Defaults to UTF-8
  • String targetFileExtension
    The filename extension that should be used for the minified/compressed CSS file. Defaults to .min.css
  • String targetEncoding (since 1.4.0) The encoding of the target CSS files to be used for writing the CSS file. Defaults to UTF-8.

News and noteworthy

  • v7.0.2 - 2024-03-28
    • Updated to ph-commons 11.1.5
    • Created Java 21 compatibility
  • v7.0.1 - 2023-07-31
    • Updated to ph-commons 11.1
  • v7.0.0 - 2023-02-01
    • Using Java 11 as the baseline
    • Updated to ph-commons 11
  • v6.5.0 - 2022-01-28
    • Re-added explicit support for deprecated property names starting with $ or * but only inside style declarations. See issue #84 and PR #85 - thanks @shagkur
    • Therefore ICSSParseErrorHandler.onCSSDeprecatedProperty was added
  • v6.4.4 - 2022-01-18
    • Added support for :host-context. See issue #80 and PR #81 - thanks @shagkur
    • Improved support for the scientific number parsing. See issue #82 and PR #83 - thanks @shagkur
  • v6.4.3 - 2022-01-13
    • Extended API of CSSReaderDeclarationList. See issue #78 - thanks @shagkur
    • Added support for the scientific number (as in 1e6) support in parsing. See issue #79 - thanks @shagkur
  • v6.4.2 - 2022-01-12
    • Improved support for :host and ::slotted. See issue #77 - thanks @shagkur
    • Added a possibility to differentiate between String and Identifier in CSSExpressionMemberTermSimple. See issue #75 and PR #76 - thanks @shagkur
  • v6.4.1 - 2022-01-10
    • Added support for :host and ::slotted. See issue #73 and PR #74 - thanks @shagkur
    • Renamed the "math*" rules to "calc*" - that also touched a few internal constants
    • Fixed the emitting of pseudo selector functions without parameters (as in :lang()). See issue #72) - thanks @shagkur
    • Updated to latest version of ParserGeneratorCC for a bit more efficient code
  • v6.4.0 - 2021-11-22
    • Fixed SonarCloud issues
    • Removed the serialisability of the objects, because it was never done in a consistent way
    • Added support for the flex shorthand property
  • v6.3.4 - 2021-06-09
    • Fixed an error with the shorthand expansion of border-width. See PR #68 - thanks @rockwotj
  • v6.3.3 - 2021-05-31
    • Allow unknown rules inside @media rules. See issue #67 - thanks @yinkwok-ys
  • v6.3.2 - 2021-05-25
    • Fixed an error with the negation parameters. See issue #66 - thanks @rockwotj
  • v6.3.1 - 2021-05-02
    • Added support for @footnote in @page rules. See PR #64 - thanks @schmidti159
  • v6.3.0 - 2021-03-22
    • Updated to ph-commons 10
  • v6.2.4 - 2021-02-25
    • Updated to ph-commons 9.4.6, leading to a more resilient DataURL parsing
    • Fixed the ignorance of minimum and maximum parameter count in class CSSPropertyColors
    • Fixed the case-sensitivity of CSS variables declarations. See issue #63
  • v6.2.3 - 2020-05-14
    • Fixed an issue with the URL visitor not recursively descending into expression members. See issue #59
  • v6.2.2 - 2020-03-29
    • Updated to ph-commons 9.4.0
  • v6.2.1 - 2020-02-29
    • Improved the pattern for colors in hex values. See PR #55.
    • Fixed a grammar issue that resulted in failed calc parsing (issue #57). The implications of this change are, that the special IE6 and IE7 hacks with $ and * as identifier prefixes are no longer supported. If you need to parse CSS suitable for these old browsers, stay with v6.2.0.
    • Updated CSS properties of the completed specifications
  • v6.2.0 - 2019-06-30
    • Fixed NPE in CSSWriterSettings.DEFAULT_SETTINGS because of wrong initialization order (#53)
    • Added some -o- media expression features
    • Changing browser compliant parsing in a way, so that less null is returned in parsing (#41)
    • The default "custom error handler" for parsing was changed from ThrowingCSSParseErrorHandler to LoggingCSSParseErrorHandler for best browser compliant mode handling
    • Improved fault tolerance in parsing when "browser compliant mode" is enabled
  • v6.1.3 - 2019-06-12
    • Added some performance tweaks
    • Added possibility to disable the usage of the source location using CSSReaderSettings (for performance reasons)
  • v6.1.2 - 2019-02-17
    • Extended list of known media expression features (e.g. used in Bootstrap 4)
  • v6.1.1 - 2018-04-11
    • Allow nested calc function (#48)
  • v6.1.0 - 2018-03-23
    • Fixed a grammar issue for calc with spaces (as in width: calc( 100% - 2.4em );)
    • Removed dependency upon java.awt.Color for improved Android compatibility.
  • v6.0.0 - 2017-12-20
    • Extracted base class AbstractHasTopLevelRules for type-safe access of top-level rules (#39)
    • Updated to ph-commons 9.0.0
    • Extended API to more easily access the CSS declaration expression string (#43)
    • Data URI scheme is treated case-insensitive (#44)
    • Extended API for easier CSS property comparison (#45)
  • v5.0.4 - 2017-04-06
    • Improved special identifier handling in expressions (#38)
    • Added support for css-grid spec with new "line-name" syntax element
    • Added new CSS units: fr, vmax and Q
  • v5.0.3 - 2017-01-09
    • Binds to ph-commons 8.6.0
    • Added custom callback for illegal characters
  • v5.0.2 - 2016-10-21
    • Made tab size configurable (issue #29)
    • Improved media expressions (issue #30)
    • Allowing to disable consistency checks in class CSSValue
    • Made CSS interpretation warnings customizable with class ICSSInterpretErrorHandler (issue #33)
  • v5.0.1 - 2016-08-17
    • Using "modern java template" for JavaCC parser - results in quicker execution
    • Enhancement issue #27
    • Integrated ph-csscompress-maven-plugin into this repository
    • Bug fix wrong OutputStream (issue #28)
  • v5.0.0 - 2016-06-12
    • Using JDK8 as the basis
    • removed explicit grammar for CSS 2.1 (issue #20)
    • Added browser compliant error handler
  • v4.2.0 - 2018-03-22
    • Removed dependency upon java.awt.Color for improved Android compatibility.
  • v4.1.6 - 2016-10-21
    • Made CSS interpretation warnings customizable with class ICSSInterpretErrorHandler (issue #33)
  • v4.1.5 - 2016-09-16
    • Improved media expressions (issue #30)
    • Integrated ph-csscompress-maven-plugin into this project (compatibility to 5.x)
  • v4.1.4 - Improved browser compliant parsing (issue #26)
  • v4.1.3 - Improved browser compliant parsing (issue #24)
  • v4.1.2 - Improved browser compliant parsing (issue #21)
  • v4.1.1 - Skipping style rules with invalid selectors in browser compliant mode; allowing "--" identifier prefix; improved unknown rule parsing (issues #17, #18, #19)
  • v4.1.0 - Improved calc parsing; extended support for page rules with page margin blocks
  • v4.0.1 - Added customizable newline characters
  • v4.0.0 - Updated to ph-commons 6.0.0 and added "browser compliant parsing mode"
  • v3.9.2 - Updated to ph-commons 5.7.1 and fix for some minor issues
  • v3.9.1 - Updated to ph-commons 5.6.0 and fix for some shorthand handling
  • v3.9.0 - API improvements and support for vendor specific "-calc" added
  • v3.8.2 - small bugfix release
  • v3.8.1 - improvements for expression parsing and single line comment handling
  • v3.8.0 - initial version in com.helger group and package

My personal Coding Styleguide | It is appreciated if you star the GitHub project if you like it.

ph-css's People

Contributors

adrienc avatar gitter-badger avatar phax avatar rockwotj avatar schmidti159 avatar shagkur avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ph-css's Issues

Another parsing exception in browser-compliant mode

Hey Philip, hope you're doing well.

We have another non-recoverable CSS exception found in the wild, so this is similar to #19.

The CSS that is causing the failure is

//...
}

;
:root .cw18winwrap {
//...
  • the semicolon in selector is the bad guy.

fyi, the CSS is found on http://www.oracle.com/technetwork/java/javase/downloads/index.html web page. And it has a bunch of other errors (as validated by csslint.net) which don't cause failures, so current state of the parser is already much closer to what browsers have in terms of error-handling.

Avoid subclassing "Error"

com.helger.css.parser.TokenMgrError extends Error. It would be better to extend Exception, or perhaps (if you do not want to avoid declaring it in the throws clause) RuntimeException. The reason being that most developers will wrap a block of code with catch(Exception) to handle any issues within it, and an Error will not be caught (because Errors are generally unrecoverable anyway). In our code, this resulted in the termination of the loop which was supposed to keep re-reading the CSS file when it changed (because an incorrect character in the CSS file caused a parse error).

A syntax error when parsing a CSS file is simply not in the same league as an "Error" (example Errors are OutOfMemoryError or a required Class file being missing).

Thank you.

References:
(1) http://www.javamex.com/tutorials/exceptions/exceptions_hierarchy.shtml
(2) http://docs.oracle.com/javase/7/docs/api/java/lang/Error.html

Error in handling of empty css block

Hello Philip, there is a one more issue from our QA.
This is example of a bit broken CSS with empty block.
https://jsfiddle.net/b49056u9/3/
As you can see "pen" is blue, because empty block was skipped.

But this code will throw NPE

String css = ".pen {background-color: red;width:100px; height:100px} {* some incorrect block *} .pen {background-color: blue}";
        CSSReaderSettings aSettings = new CSSReaderSettings()
                .setCSSVersion(ECSSVersion.LATEST)
                .setBrowserCompliantMode(true);
        CascadingStyleSheet cascadingStyleSheet = CSSReader.readFromStringStream(css, aSettings);
        CSSWriter writer = new CSSWriter(new CSSWriterSettings(ECSSVersion.LATEST, true));
        System.out.println(writer.getCSSAsString(cascadingStyleSheet));

Question - easier way to get all rules of multiple types?

Hello. I'm digging into this library for the first time and am trying to parse a stylesheet, in order to pull all font-family/ font-face declarations out of it. I've found that to be rather difficult - when working with a stylesheet instance, I have to call getAllStyleRules, getAllMediaRules, etc. etc., and iterate my way through many layers.

Is there any way to do this easier, without requiring so many manual calls? I would use getAllRules but that returns a very generic rule instance (ICSSTopLevelRule), and I'm trying to avoid having a large if statement chain within my code to check for relevant class instances, just to retrieve child declarations.

java.lang.NullPointerException: The value of 'CSS' may not be null!

Parsing a particular CSS, I get :

java.lang.NullPointerException: The value of 'CSS' may not be null!
at com.helger.commons.ValueEnforcer.notNull(ValueEnforcer.java:86)
at com.helger.css.decl.visit.CSSVisitor.visitCSS(CSSVisitor.java:378)
at com.helger.css.decl.visit.CSSVisitor.visitCSSUrl(CSSVisitor.java:416)
at TestCSS.readFromStyleAttributeWithAPI(TestCSS.java:68)
at TestCSS.main(TestCSS.java:44)

I use attached code
TestCSS.java.zip
Attached css file:
test.css.zip

Thanks

Is there a Lax Parser ?

Hello,
Currently, my understanding of parsing is that you have to set a CSS version.
Is there a Relax parser that is able to understand different versions ?
In fact I am only interested in parsing URLs, I used com.helger.css.decl.visit.DefaultCSSUrlVisitor and the sample code referenced in your documentation.
Thanks

NPE on readFromString

CascadingStyleSheet css = CSSReader.readFromString(css, Charset.forName("UTF-8"), ECSSVersion.CSS30);

This simply returns null.

The CSS that is being feed into CSSReader is actually output from jsass and can be found here:
http://pastebin.com/2ZiwyeaF

(don't judge, we are in the middle of a refactor)

Any insight would be greatly appreciated!

Cheers!

It doesn't skip well when paring CSS Expression

What steps will reproduce the problem?

  1. parsing CSS Expression with overlapped with parentheses ( "(", ")" )
  2. and write to String using CSSWriter
  3. and then you can get Expression with just one closing parenthes

What is the expected output? What do you see instead?
original data

top:expression(eval(document.documentElement.scrollTop+document.documentElement.clientHeight-this.offsetHeight));

written by CSSWriter

top:expression(eval(document.documentElement.scrollTop+document.documentElement.clientHeight-this.offsetHeight);

it should be "));" at the end of the line.
because of this the browser does not analyze after that line.

What version of the product are you using? On what operating system?
phloc-css 3.7.7
OS X 10.9
JDK 1.7

Please provide any additional information below.

https://www.hyundaicard.com/css/layout_web.css

Appengine does not yet support java 8

Philip, my build using ps-css version 5.0.1 cannot be uploaded to appengine.
For now I am building with 4.1.5.
I don't know if or when Google plan to make java 8 available on appengine, but I'm telling you, because you made a great library, and I imagine there will be many other GAE devs anting to use it.

Thanks

Ian

could not import com.helger.commons.*;

Hello Philip,
Thank you for offering such a great project.
I copy paste the source file to my java project and some errors were found in
> com.helger.css.decl.visit.CSSVisitor
> com.helger.css.CSSFilenameHelper
> com.helger.css.CCSS
because there is no com.helger.commons.* package in this project.

Skipping too much CSS if found error in browser-compliant mode

Hi again Philip, not a long time has passed =)

Here's another one from us.

Parser skips a bit more than browsers do.

public void proof()
{
            String css = "/* correct part */\n" +
                "table.fast th, table.fast td {\n" +
                "    padding: 10px 10px;\n" +
                "    text-align: left;\n" +
                "}\n" +
                "/* error that should be skipped*/\n" +
                "table.fast th background:#eee;\n" +
                "/* correct part that will be skipped too*/\n" +
                "div.flexible-detail-left {\n" +
                "    margin-bottom: 30px;\n" +
                "}\n" +
                "/* end of skipped part*/\n" +
                "@media (min-width: 700px) {\n" +
                "    div.flexible-detail-left {\n" +
                "        float: left;\n" +
                "        width: 50%;\n" +
                "        clear: left;\n" +
                "        margin-bottom: 0;\n" +
                "    }\n" +
                "\n" +
                "    div.flexible-detail-right {\n" +
                "        float: right;\n" +
                "        width: 48%;\n" +
                "        clear: right;\n" +
                "    }\n" +
                "}\n" +
                "/* correct part in the end of css*/\n" +
                "@media (min-width: 960px) {\n" +
                "    div.flexible-detail-left {\n" +
                "        width: 60%;\n" +
                "    }\n" +
                "\n" +
                "    div.flexible-detail-right {\n" +
                "        width: 37%;\n" +
                "    }\n" +
                "}\n";
        CSSReaderSettings aSettings = new CSSReaderSettings()
                .setCSSVersion(ECSSVersion.LATEST)
                .setBrowserCompliantMode(true);

        CascadingStyleSheet cascadingStyleSheet = CSSReader.readFromStringStream(css, aSettings);

        CSSWriter writer = new CSSWriter(new CSSWriterSettings(ECSSVersion.LATEST, true));

        System.out.println(writer.getCSSAsString(cascadingStyleSheet));
}

Duplicate file when bundling for Android

Apologies for the poor bug report, but I'm hoping that this might ring a bell regardless.

I've been trying to include your library (4.0.0) in an Android project, but upon compiling I get this error:

Error:Gradle: Execution failed for task ':app:packageDebug'.
> Duplicate files copied in APK META-INF/buildinfo.xml
    File 1: /home/pascal/.gradle/caches/modules-2/files-2.1/com.helger/ph-commons/6.1.0/7f96428cbbf7e4c88e9663d09070f24792321254/ph-commons-6.1.0.jar
    File 2: /home/pascal/.gradle/caches/modules-2/files-2.1/com.helger/ph-css/4.0.0/3a0ce4d7bcd6eb6a162c3d8336fb70d2c0e4a4fa/ph-css-4.0.0.jar

Unfortunately I have no idea what the buildinfo.xml is for and why this would be a problem. Have you seen this before? Is this expected? Is the Android build system just broken?

Thank you!

Please support IE media type hacks like @media all\0

Hello Philip.
We found one minor issue in CSS parsing.
Parser doesn't support IE hacks like these
http://keithclark.co.uk/articles/moving-ie-specific-css-into-media-blocks/media-tests/
Could you add support for this one in 4.* thread?
Here is snippet to reproduce the issue.
String css = "@media \\0screen\\,screen\\9 {.test {margin-left: 0px}}"; CSSReaderSettings aSettings = new CSSReaderSettings() .setCSSVersion(ECSSVersion.LATEST) .setBrowserCompliantMode(true); CascadingStyleSheet cascadingStyleSheet = CSSReader.readFromStringStream(css, aSettings); CSSWriter writer = new CSSWriter(new CSSWriterSettings(ECSSVersion.LATEST, true)); System.out.println(writer.getCSSAsString(cascadingStyleSheet));

CSSReader returns null when there is an error in the CSS string

We are having this code that loads the CSS from a string:

CSSReaderSettings settings = new CSSReaderSettings();
settings.setCSSVersion(ECSSVersion.CSS30);
settings.setBrowserCompliantMode(false);

return CSSReader.readFromStringReader(initialStyles, settings); 

If there is an error, for instance, if there is something malformed in the CSS (throws an Unrecoverable Error ), or incorrect in a line it returns null. There is any way to have it return everything but deleting the failing line?

For example:

@media (min--moz-device-pixel-ratio: 1.3),(-o-min-device-pixel-ratio: 2.6/2),(-webkit-min-device-pixel-ratio: 1.3),(min-device-pixel-ratio: 1.3),(min-resolution: 1.3dppx) {
 .social .facebook a, .social .twitter a {
  background-size: -webkit-background-size: 652px 295px;
  background-size: 652px 295px;
 }
}

Desired output, basicilly to ignore the failing line:

@media (min--moz-device-pixel-ratio: 1.3),(-o-min-device-pixel-ratio: 2.6/2),(-webkit-min-device-pixel-ratio: 1.3),(min-device-pixel-ratio: 1.3),(min-resolution: 1.3dppx) {
 .social .facebook a, .social .twitter a {
  background-size: 652px 295px;
 }
}

Pseudo function "or" identifier/string param and OR token collision.

Hi,

I'm getting this error:

12:12:47.355 [main] ERROR c.h.c.h.LoggingCSSParseExceptionCallback - Failed to parse CSS: [1:9] Encountered text 'or' corresponding to token "or". Was expecting one of: <S>, "+", "-", ")", <STRING1>, <STRING2>, <NUMBER>, <HASH>, "inherit", "from", "to", <IDENT>, <EM>, <EX>, <PX>, <REM>, <VW>, <VH>, <VMIN>, <CH>, <DPI>, <DPCM>, <DPPX>, <LENGTH_CM>, <LENGTH_MM>, <LENGTH_IN>, <LENGTH_PT>, <LENGTH_PC>, <ANGLE_DEG>, <ANGLE_RAD>, <ANGLE_GRAD>, <ANGLE_TURN>, <TIME_MS>, <TIME_S>, <FREQ_HZ>, <FREQ_KHZ>, <PERCENTAGE>, <URL>, <FUNCTION_CALC>, "expression(", <FUNCTION>, <URANGE>

with the following minimal test case.

CascadingStyleSheet cascadingStyleSheet = CSSReader.readFromString("h1:lang(or) {}", ECSSVersion.LATEST);

this is derived from some css from the web which contained:

  h2:lang(anp), h3:lang(anp), h4:lang(anp), h5:lang(anp), h6:lang(anp), h2:lang(as), h3:lang(as), h4:lang(as), h5:lang(as), h6:lang(as), h2:lang(bho), h3:lang(bho), h4:lang(bho), h5:lang(bho), h6:lang(bho), h2:lang(bh), h3:lang(bh), h4:lang(bh), h5:lang(bh), h6:lang(bh), h2:lang(bn), h3:lang(bn), h4:lang(bn), h5:lang(bn), h6:lang(bn), h2:lang(gu), h3:lang(gu), h4:lang(gu), h5:lang(gu), h6:lang(gu), h2:lang(hi), h3:lang(hi), h4:lang(hi), h5:lang(hi), h6:lang(hi), h2:lang(kn), h3:lang(kn), h4:lang(kn), h5:lang(kn), h6:lang(kn), h2:lang(ks), h3:lang(ks), h4:lang(ks), h5:lang(ks), h6:lang(ks), h2:lang(ml), h3:lang(ml), h4:lang(ml), h5:lang(ml), h6:lang(ml), h2:lang(mr), h3:lang(mr), h4:lang(mr), h5:lang(mr), h6:lang(mr), h2:lang(my), h3:lang(my), h4:lang(my), h5:lang(my), h6:lang(my), h2:lang(mai), h3:lang(mai), h4:lang(mai), h5:lang(mai), h6:lang(mai), h2:lang(ne), h3:lang(ne), h4:lang(ne), h5:lang(ne), h6:lang(ne), h2:lang(new), h3:lang(new), h4:lang(new), h5:lang(new), h6:lang(new), h2:lang(or), h3:lang(or), h4:lang(or), h5:lang(or), h6:lang(or), h2:lang(pa), h3:lang(pa), h4:lang(pa), h5:lang(pa), h6:lang(pa), h2:lang(pi), h3:lang(pi), h4:lang(pi), h5:lang(pi), h6:lang(pi), h2:lang(sa), h3:lang(sa), h4:lang(sa), h5:lang(sa), h6:lang(sa), h2:lang(ta), h3:lang(ta), h4:lang(ta), h5:lang(ta), h6:lang(ta), h2:lang(te), h3:lang(te), h4:lang(te), h5:lang(te), h6:lang(te) { line-height: 1.2em; }

I think it has to do with the terminal tokens defined in the grammar, one of which is 'or'. This probably collides with the expr rule somehow that is used for pseudo functions. Probably needs same hack as here: https://github.com/phax/ph-css/blob/master/ph-css/src/main/jjtree/ParserCSS30.jjt#L767

CSSURI with non-lower-case scheme not recognized as data uri

As stated in RFC 3986:

Although schemes are case-
insensitive, the canonical form is lowercase and documents that
specify schemes must do so with lowercase letters. An implementation
should accept uppercase letters as equivalent to lowercase in scheme
names (e.g., allow "HTTP" as well as "http") for the sake of
robustness but should only produce lowercase scheme names for
consistency.

But ph-css version 5.0.4 does not treat non-lowercase URIs as data URIs, eg.:

new CSSURI("DaTa:,someData").isDataURL()

returns false even though it should return true.

I believe that’s a minor bug.

Such URIs are not very common (and probably even less so in CSS files), yet when you try to handle all wild varieties of things that happen on the web in a fashion similar to web browser, this behaviour becomes an issue and a user of the library needs to manually check URI scheme.

Deprecate CSSDeclaration.setProperty(String), use enum instead

Currently, a string property "m_sProperty" is used, can we switch to ECSSProperty? That will make the client code much easier and tidier.

E,g.

new DefaultCSSVisitor() {
   @Override public void onDeclaration(@Nonnull CSSDeclaration declaration) {
        // currently:
        if (declaration.getProperty().equals("font") { ... }
        // prefer enum:
        if (declaration.getPropName() == ECSSProperty.FONT) { ...}
    }
};

How to get a simple style?

Hi
I am a newbie in you library, I have Style.css as :

.qsign
{
    color:red;
}

I read a css using this :

    var cssString = Utils.readStringFromAssets(context, "Style.css")
    css=CSSReader.readFromString(cssString,ECSSVersion.CSS30)

Now how can I get color of qsign class?

Nested calc() rules cause parse error

As stated in https://developer.mozilla.org/en-US/docs/Web/CSS/calc, calc() rules may be nested as in height: calc(calc(2.25rem + 2px) - 1px * 2); (taken form the bootstrap 4 CSS rules).

Unfortunately, this seems to break the stylesheet parser causing the following error:

com.helger.css.parser.ParseException: Encountered unexpected token: "calc(" <FUNCTION_CALC>
    at line 3831, column 16.

Was expecting one of:

    "("
    "+"
    "-"
    "expression("
    <ANGLE_DEG>
    <ANGLE_GRAD>
    <ANGLE_RAD>
    <ANGLE_TURN>
    <CH>
    <DPCM>
    <DPI>
    <DPPX>
    <EM>
    <EX>
    <FR>
    <FREQ_HZ>
    <FREQ_KHZ>
    <FUNCTION>
    <LENGTH_CM>
    <LENGTH_IN>
    <LENGTH_MM>
    <LENGTH_PC>
    <LENGTH_PT>
    <LENGTH_Q>
    <NUMBER>
    <PERCENTAGE>
    <PX>
    <REM>
    <S>
    <TIME_MS>
    <TIME_S>
    <VH>
    <VMAX>
    <VMIN>
    <VW>

	at com.helger.css.parser.ParserCSS30.generateParseException(ParserCSS30.java:6696)
	at com.helger.css.parser.ParserCSS30.jj_consume_token(ParserCSS30.java:6554)
	at com.helger.css.parser.ParserCSS30.mathUnit(ParserCSS30.java:1017)
	at com.helger.css.parser.ParserCSS30.mathProduct(ParserCSS30.java:1091)
	at com.helger.css.parser.ParserCSS30.mathSum(ParserCSS30.java:1184)
	at com.helger.css.parser.ParserCSS30.math(ParserCSS30.java:1217)
	at com.helger.css.parser.ParserCSS30.exprTerm(ParserCSS30.java:1479)
	at com.helger.css.parser.ParserCSS30.expr(ParserCSS30.java:1622)
	at com.helger.css.parser.ParserCSS30.styleDeclaration(ParserCSS30.java:3090)
	at com.helger.css.parser.ParserCSS30.styleDeclarationOrRule(ParserCSS30.java:3131)
	at com.helger.css.parser.ParserCSS30.styleDeclarationList(ParserCSS30.java:3376)
	at com.helger.css.parser.ParserCSS30.styleDeclarationBlock(ParserCSS30.java:3414)
	at com.helger.css.parser.ParserCSS30.styleRule(ParserCSS30.java:3481)
	at com.helger.css.parser.ParserCSS30.styleSheet(ParserCSS30.java:379)
	at com.helger.css.reader.CSSReader._readStyleSheet(CSSReader.java:216)
	at com.helger.css.reader.CSSReader.readFromStream(CSSReader.java:1067)
	at com.helger.css.reader.CSSReader.readFromFile(CSSReader.java:765)

Missing documentation

The project looks good, but it's somehow not easy to get it work quickly.
Simple Getting Started with some code examples would help a lot.
Thanks :)

Non-browser-compliant processing of mistakenly nested @page rule

Long time, Philip. Another issue from the wild:

This:

body {
    background: green;
}

@media print {
    body {
        @page {
            margin: 0.5cm;
        }
    }

    body {
        background: red !important;
    }

}

becomes this after the transformation (formatted):

body {
    background: green;
}

@media print {
    body {
    }
}

body {
    background: red !important;
}

As you can see, rule that is targeted only for print leaks to "global" area.

Here's the fiddle where you can see that browsers don't do that: https://jsfiddle.net/zyuxschg/

Unclosed CSS rule recovers as soon as non-matching "}" is encountered (and this is not what browsers do)

Imagine we have this piece of CSS:
.class{color:red;.class{color:green}.class{color:blue}

After parsing it will become smt. like:
.class{color:red}.class{color:blue}
i.e. first closing bracket will be treated as matched and invalid rule content (.class{color:green) will be thrown away.

And browsers will throw away everything until the matching closing bracket: in our example it is everything after red;. I.e. browser would treat the example like this:
.class{color:red;}

Is it possible to tweak parser to behave more like browsers do in such cases? Maybe some configuration options?

Thanks!

Remove special CSS 2.1 parser - keep the 3.0 parser only

Hi all!

I want to remove the explicit CSS 2.1 parser from the code as well as I want to remove the version handling inside the code so that only CSS 3.0 is supported. This means that it's up to the implementer to create CSS 2.1 compliant code.

This would make the code more lightweight and I need to maintain only 1 grammaer, as I think that CSS 2.1 support is sufficient with ph-css 4.1.1 :)

Any thoughts on this?

// Philip

Source location wrong when strings contain tabs

Hi!

I have the impression that the source location information is wrong in string that contain tabs. For instance try the following code:

import com.helger.css.ECSSVersion;
import com.helger.css.decl.CascadingStyleSheet;
import com.helger.css.reader.CSSReader;

public class TestCSS {

    public static void main(String[] args) {
        CascadingStyleSheet css1 = CSSReader.readFromString("body { }", ECSSVersion.LATEST);
        System.out.println(css1.getAllStyleRules().getFirst().getSourceLocation());
        CascadingStyleSheet css2 = CSSReader.readFromString("\tbody { }", ECSSVersion.LATEST);
        System.out.println(css2.getAllStyleRules().getFirst().getSourceLocation());
    }
}

I have the following output:

[firstTokenArea=[beginLine=1; beginColumn=1; endLine=1; endColumn=4]; lastTokenArea=[beginLine=1; beginColumn=8; endLine=1; endColumn=8]]
[firstTokenArea=[beginLine=1; beginColumn=9; endLine=1; endColumn=12]; lastTokenArea=[beginLine=1; beginColumn=16; endLine=1; endColumn=16]]

I had the impression that it should be beginColumn=2 etc... for the second no?

Properly skip invalid rules

Original issue: https://code.google.com/p/phloc-css/issues/detail?id=19

When the parser finds an invalid rule, it skips this rule and all the following rules in a block. Browsers, however, skip only the invalid rule, leaving all the following rules in a block intact (this is the behavior that a few years ago was actively used by developers who created IE-specific hacks by prepending a * or a _ to a selector (http://webdesignerwall.com/tutorials/css-specific-for-internet-explorer)).

So if imagine a block like this

.box {
    background: gray; /* standard */
    *background: green; /* IE 7 and below */
    border-color: red;
}

then in the modern browsers it will be treated as this:

.box {
    background: gray; 
    border-color: red;
}

while ph parser will treat it like this:

.box {
    background: gray; 
}

Empty URL in expression leads to exception

This code

.a { background: url(''); }

causes the exception

18:48:26,118 [ERROR] ProxiedResourceHandler         - Resource content could not be transformed. java.lang.IllegalArgumentException: The value of the string 'URI' may not be empty!
        at com.phloc.commons.ValueEnforcer.notEmpty(ValueEnforcer.java:66)
        at com.phloc.css.decl.CSSURI.setURI(CSSURI.java:76)
        at com.phloc.css.decl.CSSURI.<init>(CSSURI.java:51)
        at com.phloc.css.handler.CSSNodeToDomainObject._createExpressionURL(CSSNodeToDomainObject.java:389)
        at com.phloc.css.handler.CSSNodeToDomainObject._createExpressionTerm(CSSNodeToDomainObject.java:477)
        at com.phloc.css.handler.CSSNodeToDomainObject._createExpression(CSSNodeToDomainObject.java:505)
        at com.phloc.css.handler.CSSNodeToDomainObject._createDeclaration(CSSNodeToDomainObject.java:548)
        at com.phloc.css.handler.CSSNodeToDomainObject._createStyleRule(CSSNodeToDomainObject.java:597)
        at com.phloc.css.handler.CSSNodeToDomainObject.createCascadingStyleSheetFromNode(CSSNodeToDomainObject.java:1115)
        at com.phloc.css.handler.CSSHandler.readCascadingStyleSheetFromNode(CSSHandler.java:64)
        at com.phloc.css.reader.CSSReader.readFromStream(CSSReader.java:1446)
        at com.phloc.css.reader.CSSReader.readFromString(CSSReader.java:681)

Looks like convertion to AST works fine, but when converting from AST to object empty URLs are not expected.

However, they aren't invalid from CSS point of view, so probably should be parsed just fine. Or (as they are useless anyway) they can be thrown away when converting to AST.

Parsers skips more content than browsers in case of error in browser-compliant mode

Hi Philip. So, another issue from the fields. Here's the excerpt from one CSS file, and the error-handling is slightly different as outlined in comments:

/* correct part */
table.fast th, table.fast td {
    padding: 10px 10px;
    text-align: left;
}
/* error that should be skipped*/
table.fast th background:#eee;

/* first correct part that skipped by both browsers and parser algorithm */
.ir {
    display: block;
}

/* correct part that is skipped by parser but is read by browsers */
div.flexible-detail-left {
    margin-bottom: 30px;
}
/* end of skipped part */

.some { more: css; }

NullPointerException in getAsCSSString

Test :

String css = "@font-face { font-family: 'NeutraText-Bold'; src: url(https://www.someFonts.com/NeutraText-Bold.otf); }";

        for (ICSSTopLevelRule icssTopLevelRule : CSSReader.readFromStringStream(css, ECSSVersion.LATEST).getAllRules()) {
            icssTopLevelRule.getAsCSSString();
        }

From my understanding this due to order of static field initialization in CSSWriterSettings in which DEFAULT_SETTINGS is created before the default has been set.

Workaround is to create CSSWriterSettings and setNewLineMode and pass it to getAsCSSString.

What's the License of the project

Hello,
Nice library idea, it's missing.
Under what license is it delivered ?
Ideally , an Apache 2.0 license would be great, but I don't see any LICENSE file.
Thanks

@media parse fails

Error in @media rule. (Invalid token "and". Was expecting one of: , , .)

Happens when something like this present:

@media screen and (min-width: 768px) {.section {.
    padding: 40px
}

}

keyframes kill the parser

When the css has @-webkit-keyframes, @moz-keyframes etc you get a null stylesheet from:

CollectingCSSParseErrorHandler aErrors = new CollectingCSSParseErrorHandler(new LoggingCSSParseErrorHandler());

final CascadingStyleSheet stylesheet = CSSReader.readFromString(cssFileContent, ECSSVersion.CSS30, aErrors);

Luckily, I can use the sourceforge CSSOMParser to extract the keyframes rules before running the remaing css through your parser.

Unsupported Class file version 52.0 Android

Good afternoon,
Apologies for the poor grammar and supposed bug. I'm newer developer in android studio.
I trying to use your library with gradle/maven and when i run the app this message shows:

Error:PARSE ERROR:
Error:unsupported class file version 52.0
Error:...while parsing com/helger/commons/CGlobal.class
Error:1 error; aborting
:app:transformClassesWithDexForDebug FAILED
Error:Execution failed for task ':app:transformClassesWithDexForDebug'.
> com.android.build.api.transform.TransformException: java.lang.RuntimeException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'C:\Program Files\Java\jdk1.8.0_65\bin\java.exe'' finished with non-zero exit value 1

I tried to use this post in stackoverflow
http://stackoverflow.com/questions/37902840/got-unsupported-class-file-version-52-0-after-including-a-module-to-a-project
Nothing happens...
And when i saw your changelog about jdk 8, i tried to use this instead:
https://developer.android.com/preview/j8-jack.html?hl=en
I removed the duplicate files and this message shows:

Error:Library reading phase: Type javax.annotation.Untainted from file 'C:\Users\user\AndroidStudioProjects\CSSTest\app\build\intermediates\jill\debug\packaged\jsr305-3.0.1-dd0e9f5d0efb3025f6fde4238fd4a5c268f62a63.jar' has already been imported from file 'C:\Users\user\AndroidStudioProjects\CSSTest\app\build\intermediates\jill\debug\packaged\annotations-3.0.1u2-2b84c751906484cab0381cba276af74c2923d73b.jar', type 'javax.annotation.Untainted' (see property 'jack.import.type.policy' for type collision policy)
com.android.jack.api.v01.CompilationException: Library reading phase: Type javax.annotation.Untainted from file 'C:\Users\user\AndroidStudioProjects\CSSTest\app\build\intermediates\jill\debug\packaged\jsr305-3.0.1-dd0e9f5d0efb3025f6fde4238fd4a5c268f62a63.jar' has already been imported from file 'C:\Users\user\AndroidStudioProjects\CSSTest\app\build\intermediates\jill\debug\packaged\annotations-3.0.1u2-2b84c751906484cab0381cba276af74c2923d73b.jar', type 'javax.annotation.Untainted' (see property 'jack.import.type.policy' for type collision policy)

Error on parsing url(data:image:...)

We are having trouble with some url properties with url(data:image). For example this CSS:

.hamburger {
  | background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath style='fill:#ffffff;' d='M820 500c14 0 26-6 36-16s14-22 14-36c0-14-4-26-14-36-12-10-24-16-36-16 0 0-616 0-616 0-12 0-24 6-36 16-10 10-14 22-14 36s4 26 14 36c10 10 22 16 36 16 0 0 616 0 616 0zM204 602c-12 0-24 4-36 14-10 12-14 24-14 36 0 14 4 26 14 36s22 16 36 16c0 0 616 0 616 0 14 0 26-6 36-16s14-22 14-36c0-12-4-24-14-36-12-10-24-14-36-14 0 0-616 0-616 0zM820 294c14 0 26-4 36-14 10-12 14-24 14-36 0-14-4-26-14-36-12-10-24-16-36-16 0 0-616 0-616 0-12 0-24 6-36 16-10 10-14 22-14 36 0 12 4 24 14 36 10 10 22 14 36 14 0 0 616 0 616 0z'/%3E%3C/svg%3E");
  | background-position: left 6px center;
  | background-repeat: no-repeat;
  | display: block;
  | position: absolute;
  | width: 36px;
  | height: 29px;
  | z-index: 1000;
  | top: 1rem;
  | left: 0.9rem;
  | }

If I convert it and print it. It gets transformed to:

.hamburger {
  background:url("http://localhost.comdata:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath style='fill:#ffffff;' d='M820 500c14 0 26-6 36-16s14-22 14-36c0-14-4-26-14-36-12-10-24-16-36-16 0 0-616 0-616 0-12 0-24 6-36 16-10 10-14 22-14 36s4 26 14 36c10 10 22 16 36 16 0 0 616 0 616 0zM204 602c-12 0-24 4-36 14-10 12-14 24-14 36 0 14 4 26 14 36s22 16 36 16c0 0 616 0 616 0 14 0 26-6 36-16s14-22 14-36c0-12-4-24-14-36-12-10-24-14-36-14 0 0-616 0-616 0zM820 294c14 0 26-4 36-14 10-12 14-24 14-36 0-14-4-26-14-36-12-10-24-16-36-16 0 0-616 0-616 0-12 0-24 6-36 16-10 10-14 22-14 36 0 12 4 24 14 36 10 10 22 14 36 14 0 0 616 0 616 0z'/%3E%3C/svg%3E");
  background-position:left 6px center;
  background-repeat:no-repeat;
  display:block;
  position:absolute;
  width:36px;
  height:29px;
  top:1rem;
  left:0.9rem;
}

Adding the hostname in front of the data:image.

Is this a known bug or something it can be avoided?

Thanks!

Not parsing hrefs inside svg tag

E.g. on the pexels.com website:

 <a class="tiny-profile" data-track-action="home" data-track-label="leaderboard-item" href="/u/ibrahim-asad-45786/"> <img alt="Ibrahim Asad" class="tiny-profile__img" width="30" height="30" src="https://www.gravatar.com/avatar/5fbff6603f724a3b6bfc68b0172ed30b?s=60&amp;d=retro"> <span class="tiny-profile__name">Ibrahim Asad</span> <span class="tiny-profile__downloads"> 
   <svg viewbox="0 0 100 100" class="tiny-profile__downloads-icon">
    <use xlink:href="#iconDownloads"></use>
   </svg> 4.01K </span> </a> 

Chrome shows: Unsafe attempt to load URL http://pexels.com/ from frame with URL http://dev.htmlhub.io:8888/?bookmark-admin=pexels. Domains, protocols and ports must match.

While the above example looks like the href might not actually be a server url, Chrome thinks it is, and anyhow, it didn't get picked up by AbstractModifyingCSSUrlVisitor.

BTW = fantastic library for replacing css embedded urls with data urls. Many thanks. Much appreciated.

Ian

AWT dependencies in ECSSColor and CSSColorHelper and Android usage of ph-css

Hi Philip,
We are using ph-css in our Android-App.
Today I started implementing parsing of colors and discovered, that there are dependencies to AWT in bot ECSSColor and CSSColorHelper. However, there is no AWT support on Android that I know of.
So sadly, I can't make use of those classes/ enums to determine what kind of Color it is, the CSS contains or get RGB values of named CSS colors.

The root of all evil lies in
final float [] aHSL = CSSColorHelper.getRGBAsHSLValue (nRed, nGreen, nBlue);
of ECSSColor's constructor. Is there a possibility or plan for you to ditch AWT dependencies, or move them somewhere else, so we don't have to have AWT in order to use ECSSColor?

Error when parsing data URIs

Hi, your tool is great, but I can't parse (and I'd need to) data URIs, like for example:

background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzJkYWZkOCIgc3RvcC1vcGFjaXR5PSIwIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwYTU5ODUiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);

I'd appreciate if this was supported, given that it is becoming a common feature of css style sheets.

thanks!

-webkit-calc unparseable

Hello,

Many thanks for the tool.

I have just noticed that rules containing the -webkit-calc math function cannot be parsed, and are omitted from the stylesheet.

Thanks,
Emmanuel

Invalid selector is causing unrecoverable error

Hi again Philip, it's been a while!

I am having the following situation and I wonder if you could give any advice here. It's possible that it's not your parser's responsibility but perhaps you could point to a way to work around this with your APIs.

So, one of the goals of our application when it comes to CSS parsing is to transform all the url()-s in it. We do so by using the CSSVisitor.visitCSSUrl() method.

However, when we have CSS like this:

body {
    background: url(../bg.png);
}
.#f { color: red; }

the parser fails unrecoverably on the .#f selector and so we're unable to transform the URLs. We're using v4.0.0 with CSS3 parser and .setBrowserCompliantMode(true) - which, as I imagined, shouldn't have treated such error as unrecoverable - as browser doesn't.

Sorry if my questions are noob - I am by no means a Java programmer. Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.