// $Id$ // Author: Jean-Guilhem Rouel // (c) COPYRIGHT MIT, ERCIM and Keio, 2005. // Please first read the full copyright statement in file COPYRIGHT.html package org.w3c.css.selectors; import org.w3c.css.parser.CssSelectors; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionDir; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionHas; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionHost; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionHostContext; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionIs; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionLang; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionNot; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionNthChild; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionNthCol; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionNthLastChild; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionNthLastOfType; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionNthOfType; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionSlotted; import org.w3c.css.selectors.pseudofunctions.PseudoFunctionWhere; import org.w3c.css.util.ApplContext; import org.w3c.css.util.CssProfile; import org.w3c.css.util.CssVersion; import org.w3c.css.util.InvalidParamException; import org.w3c.css.values.CssExpression; import java.util.ArrayList; /** * PseudoFactory
* Created: Sep 2, 2005 2:41:09 PM
*/ public class PseudoFactory { private static final String[] PSEUDOCLASS_CONSTANTSCSS3 = { // https://www.w3.org/TR/2018/WD-selectors-4-20181121/#location "any-link", "link", "visited", "local-link", "target", "target-within", "scope", // https://www.w3.org/TR/2018/WD-selectors-4-20181121/#useraction-pseudos "hover", "active", "focus", "focus-visible", "focus-within", // https://www.w3.org/TR/2018/WD-selectors-4-20181121/#time-pseudos "current", "past", "future", // https://www.w3.org/TR/2018/WD-selectors-4-20181121/#resource-pseudos "playing", "paused", // https://www.w3.org/TR/2018/WD-selectors-4-20181121/#input-pseudos "enabled", "disabled", "read-only", "read-write", "placeholder-shown", "default", "checked", "indeterminate", "blank", "valid", "invalid", "in-range", "out-of-range", "required", "optional", "user-invalid", // https://www.w3.org/TR/2018/WD-selectors-4-20181121/#structural-pseudos "root", "empty", "first-child", "last-child", "only-child", "first-of-type", "last-of-type", "only-of-type", // https://www.w3.org/TR/2018/WD-css-page-3-20181018/#page-selectors "left", "right", "first", // https://www.w3.org/TR/2014/WD-css-scoping-1-20140403/#selectordef-host0 "host", // https://fullscreen.spec.whatwg.org/#:fullscreen-pseudo-class "fullscreen", // https://html.spec.whatwg.org/multipage/semantics-other.html#pseudo-classes "autofill", "defined" }; private static final String[] PSEUDOCLASS_CONSTANTSCSS2 = { "link", "visited", "active", "focus", "hover", "first-child" }; private static final String[] PSEUDOCLASS_CONSTANTSTV = { "link", "visited", "active", "focus", "first-child" }; private static final String[] PSEUDOCLASS_CONSTANTSCSS1 = { "link", "visited", "active" }; private static final String[] PSEUDOCLASS_CONSTANTS_MOBILE = { "link", "visited", "active", "focus" }; private static final String[] PSEUDOELEMENT_CONSTANTSCSS3 = { // https://www.w3.org/TR/2020/WD-css-pseudo-4-20201231/#typographic-pseudos "first-line", "first-letter", // https://www.w3.org/TR/2020/WD-css-pseudo-4-20201231/#highlight-pseudos "selection", "target-text", "spelling-error", "grammar-error", // https://www.w3.org/TR/2020/WD-css-pseudo-4-20201231/#treelike "before", "after", "marker", "placeholder", "file-selector-button", // https://fullscreen.spec.whatwg.org/#::backdrop-pseudo-element "backdrop", // https://www.w3.org/TR/2019/CR-webvtt1-20190404/#css-extensions "cue", "cue-region", // https://www.w3.org/TR/2014/WD-css-scoping-1-20140403/ (20211001 draft) "content", "shadow" }; private static final String[] PSEUDOELEMENT_CONSTANTSCSS2 = { "first-line", "first-letter", "before", "after" }; private static final String[] PSEUDOELEMENT_CONSTANTSCSS1 = { "first-line", "first-letter" }; private static final String[] PSEUDOCLASS_FUNCTION_CONSTANTSCSS3 = { "nth-child", "nth-last-child", "nth-of-type", "nth-last-of-type", "lang", "not" // from selectors-4 unstable list (20190624) , "nth-col", "nth-last-col", "is", "where", "has", "dir", // // https://www.w3.org/TR/2014/WD-css-scoping-1-20140403/ "host", "host-context", "slotted" }; private static final String[] PSEUDOFUNCTION_CONSTANTSCSS2 = { "lang" }; /** * Returns the possible pseudo-classes for a version/profile pair * * @param version the CSS Level to get associated pseudo-classes definitions * @param profile the profile to get associated pseudo-classes * @return the possible pseudo-classes for the version/profile */ public static String[] getPseudoClass(CssVersion version, CssProfile profile) { // TODO we might need some merging in some cases // unused for now, but leaving the TODO to find it easily. switch (profile) { case TV: return PSEUDOCLASS_CONSTANTSTV; case MOBILE: return PSEUDOCLASS_CONSTANTS_MOBILE; } // not one of a specific version, let's match on CSS Version switch (version) { case CSS1: return PSEUDOCLASS_CONSTANTSCSS1; case CSS2: case CSS21: return PSEUDOCLASS_CONSTANTSCSS2; case CSS3: return PSEUDOCLASS_CONSTANTSCSS3; } // and the default return null; } /** * Returns the possible pseudo-elements for a profile * * @param version the CSS Version^Wlevel to get associated pseudo-elements * @return the possible pseudo-elements for the profile */ public static String[] getPseudoElement(CssVersion version) { switch (version) { case CSS2: case CSS21: return PSEUDOELEMENT_CONSTANTSCSS2; case CSS3: return PSEUDOELEMENT_CONSTANTSCSS3; case CSS1: return PSEUDOELEMENT_CONSTANTSCSS1; default: return null; } } /** * Returns the possible pseudo-functions for a profile * * @param version the profile to get associated pseudo-functions * @return the possible pseudo-functions for the profile */ public static String[] getPseudoFunction(CssVersion version) { switch (version) { case CSS2: case CSS21: return PSEUDOFUNCTION_CONSTANTSCSS2; case CSS3: return PSEUDOCLASS_FUNCTION_CONSTANTSCSS3; case CSS1: default: return null; } } /** * Returns the possible pseudo-elements written as pseudo-classes * for a specific profile * * @param version the profile to get associated exceptions to the rule * @return the possible pseudo-elements/classes for the profile */ public static String[] getPseudoElementExceptions(CssVersion version) { switch (version) { case CSS2: case CSS21: case CSS3: return PSEUDOELEMENT_CONSTANTSCSS2; case CSS1: default: return null; } } /** * Returns a PseudoFunctionSelector based on the name of the * selector * * @param name, the name of the pseudofun selector * @param value, its value * @throws InvalidParamException */ public static PseudoFunctionSelector newPseudoFunction(String name, String value, ApplContext ac) throws InvalidParamException { if (name == null) { throw new InvalidParamException("pseudo", "null pseudofunction", ac); } if (name.equals("not")) { return new PseudoFunctionNot(name, value); } if (name.equals("slotted")) { return new PseudoFunctionSlotted(name, value); } if (name.equals("host")) { return new PseudoFunctionSlotted(name, value); } if (name.equals("host-context")) { return new PseudoFunctionSlotted(name, value); } throw new InvalidParamException("pseudo", ":" + name, ac); } public static PseudoFunctionSelector newPseudoFunction(String name, ArrayList value, ApplContext ac) throws InvalidParamException { if (name == null) { throw new InvalidParamException("pseudo", "null pseudofunction", ac); } if (name.equals("not")) { return new PseudoFunctionNot(name, value); } if (name.equals("is")) { return new PseudoFunctionIs(name, value); } if (name.equals("where")) { return new PseudoFunctionWhere(name, value); } if (name.equals("has")) { return new PseudoFunctionHas(name, value); } if (name.equals("slotted")) { return new PseudoFunctionSlotted(name, value); } if (name.equals("host")) { return new PseudoFunctionHost(name, value); } if (name.equals("host-context")) { return new PseudoFunctionHostContext(name, value); } throw new InvalidParamException("pseudo", ":" + name, ac); } public static PseudoFunctionSelector newPseudoFunction(String name, CssExpression exp, ApplContext ac) throws InvalidParamException { if (name == null) { throw new InvalidParamException("pseudo", "null pseudofunction", ac); } if (name.equals("dir")) { return new PseudoFunctionDir(name, exp, ac); } if (name.equals("lang")) { return new PseudoFunctionLang(name, exp, ac); } if (name.equals("nth-col")) { return new PseudoFunctionNthCol(name, exp, ac); } if (name.equals("nth-last-col")) { return new PseudoFunctionNthCol(name, exp, ac); } throw new InvalidParamException("pseudo", ":" + name, ac); } public static PseudoFunctionSelector newPseudoFunction(String name, CssExpression exp, ArrayList selector_list, ApplContext ac) throws InvalidParamException { if (name == null) { throw new InvalidParamException("pseudo", "null pseudofunction", ac); } if (name.equals("nth-child")) { return new PseudoFunctionNthChild(name, exp, selector_list, ac); } if (name.equals("nth-last-child")) { return new PseudoFunctionNthLastChild(name, exp, selector_list, ac); } if (name.equals("nth-of-type")) { return new PseudoFunctionNthOfType(name, exp, selector_list, ac); } if (name.equals("nth-last-of-type")) { return new PseudoFunctionNthLastOfType(name, exp, selector_list, ac); } throw new InvalidParamException("pseudo", ":" + name, ac); } }