NSAC: Extending the W3C's SAC API

26 views
Skip to first unread message

admin

unread,
Sep 9, 2017, 10:13:32 AM9/9/17
to css4j-devel
This library relies on a parser implementing the SAC api to do low-level CSS parsing. That API was published as a W3C Note in 2000 and last updated 15 years ago. Until now there were two open source implementations of the API (not counting Flute nor this project's own new implementation) that are not completely interoperable, and for example none of them implements PositionalCondition.

An Updated SAC-like API

Representing level 4 selectors is not possible with the current SAC, however, so an extension had to be developed. As the original interfaces are on a package under the org.w3c hierarchy and cannot be modified directly, a set of interfaces that inherit from SAC was created under a new package called 'nsac' (for Non-Standard Api for Css) in the doc.style.css hierarchy of this project. Each file carries the following notice:

/*
 * This software includes material derived from SAC (https://www.w3.org/TR/SAC/).
 * Copyright © 1999,2000 W3C® (MIT, INRIA, Keio).
 *
 * The original version of this interface comes from SAX :
 */

The New Interfaces

The modifications that the new interfaces introduce are basically the following:

  1. LexicalUnit: add identifiers for level 3 units like SAC_CAP.
  2. Selector: add numeric identifiers for SAC_SUBSEQUENT_SIBLING_SELECTOR and SAC_COLUMN_COMBINATOR_SELECTOR.
  3. Condition: add numeric identifiers for SAC_BEGINS_ATTRIBUTE_CONDITION and others, including SAC_PSEUDO_ELEMENT_CONDITION. Pseudo-elements are handled as conditional selectors with this extension, as the current SAC seems to require the use of an 'and' condition to represent something like p:first-line (as an element plus a pseudo-element), which is complex and not supported by any publicly available SAC implementation. Also, a new Condition.SAC_SELECTOR_ARGUMENT_CONDITION identifier is introduced to support the new ArgumentCondition.
  4. New ArgumentCondition (see below).
  5. New methods added to AttributeCondition and PositionalCondition (see below).

New Methods

Interface AttributeCondition

boolean isCaseSensitive()

Is the condition case sensitive? Only returns false for attribute selectors with the i flag.


Interface PositionalCondition

boolean isForwardCondition()

Is this a forward condition? return true if this is a forward condition like :nth-child (also true for :only-child), false otherwise (like in :nth-last-child).

boolean isOfType()

Is this an of-type selector? This method only returns true if the selector has been explicitly declared to apply to the same type, like in :first-of-type or :nth-of-type. It should return false otherwise, for example for selectors like div:nth-child(1 of div) despite being equivalent to div:first-of-type.
This method is possibly the same as the old PositionalCondition.getType(), but with a potentially different specification.

int getFactor()

Get the An+B expression factor (i.e. 'A'). Zero if there is no factor (or no expression).

int getOffset()

Get the An+B expression offset (i.e. 'B'). If there is no expression, it must return the positive integer position value (e.g. 1 for :first-child or :last-child).

SelectorList getOfList()

Get the list of selectors that the child list have to match, or null if not specified.


New Interface ArgumentCondition

String getName()

Get the name of the condition, like not or has.

SelectorList getSelectors()

Get the selector list to which the condition has to be applied.


Other Changes to Current SAC Usage

Although the changes described so far are required to handle modern selectors, this project's own SAC (or NSAC) implementation has other differences in behaviour with respect to other implementations. For example, the names of pseudo-classes are retrieved with the AttributeCondition's getLocalName() method instead of getValue(). This leaves getValue() to retrieve the pseudo-class argument if there is any, like in :drop(active).

Also, the identifier SAC_ANY_NODE_SELECTOR is used for the universal selector, instead of an ElementSelector with the * local name.


Comments are Welcome

Other SAC implementations are encouraged to implement these extensions if they desire to be interoperable with this project, and comments are welcome. The NSAC files are part of the current css4j core, but they could be made a separate download (or even a separate project) if there is interest from any implementor.

I thank P. Le Hégaret and any contributors to SAC for their work, which is the foundation for this extension.

admin

unread,
Nov 15, 2017, 4:11:43 PM11/15/17
to css4j-devel
Also, the identifier SAC_ANY_NODE_SELECTOR is used for the universal selector, instead of an ElementSelector with the * local name.

One clarification is needed here: in NSAC the universal selector '*' is implemented as an ElementSelector with the * local name, but its getSelectorType() method returns SAC_ANY_NODE_SELECTOR instead of SAC_ELEMENT_NODE_SELECTOR.

The idea is that to check for the universal selector you just look at the value returned by getSelectorType(), instead of having to test for an ElementSelector with the * local name.

admin

unread,
May 26, 2018, 9:21:05 AM5/26/18
to css4j...@googlegroups.com
Support for the syntax required by the grid specification recently landed in git. It adds the following identifiers to LexicalUnitSAC_LEFT_BRACKETSAC_RIGHT_BRACKET and SAC_FRSAC_FR represents the flex (fr) unit.

The NSAC reference implementation was updated to handle both the new unit and the brackets.
Reply all
Reply to author
Forward
0 new messages