MDL-65759 library: Update php-css-parser to 8.3.0
[moodle.git] / lib / php-css-parser / Value / Value.php
CommitLineData
fbe18cc0
FM
1<?php
2
3namespace Sabberworm\CSS\Value;
4
376eb156
MM
5use Sabberworm\CSS\Parsing\ParserState;
6use Sabberworm\CSS\Parsing\UnexpectedTokenException;
fbe18cc0
FM
7use Sabberworm\CSS\Renderable;
8
9abstract class Value implements Renderable {
376eb156
MM
10 protected $iLineNo;
11
12 public function __construct($iLineNo = 0) {
13 $this->iLineNo = $iLineNo;
14 }
15
16 public static function parseValue(ParserState $oParserState, $aListDelimiters = array()) {
17 $aStack = array();
18 $oParserState->consumeWhiteSpace();
19 //Build a list of delimiters and parsed values
20 while (!($oParserState->comes('}') || $oParserState->comes(';') || $oParserState->comes('!') || $oParserState->comes(')') || $oParserState->comes('\\'))) {
21 if (count($aStack) > 0) {
22 $bFoundDelimiter = false;
23 foreach ($aListDelimiters as $sDelimiter) {
24 if ($oParserState->comes($sDelimiter)) {
25 array_push($aStack, $oParserState->consume($sDelimiter));
26 $oParserState->consumeWhiteSpace();
27 $bFoundDelimiter = true;
28 break;
29 }
30 }
31 if (!$bFoundDelimiter) {
32 //Whitespace was the list delimiter
33 array_push($aStack, ' ');
34 }
35 }
36 array_push($aStack, self::parsePrimitiveValue($oParserState));
37 $oParserState->consumeWhiteSpace();
38 }
39 //Convert the list to list objects
40 foreach ($aListDelimiters as $sDelimiter) {
41 if (count($aStack) === 1) {
42 return $aStack[0];
43 }
44 $iStartPosition = null;
45 while (($iStartPosition = array_search($sDelimiter, $aStack, true)) !== false) {
46 $iLength = 2; //Number of elements to be joined
47 for ($i = $iStartPosition + 2; $i < count($aStack); $i+=2, ++$iLength) {
48 if ($sDelimiter !== $aStack[$i]) {
49 break;
50 }
51 }
52 $oList = new RuleValueList($sDelimiter, $oParserState->currentLine());
53 for ($i = $iStartPosition - 1; $i - $iStartPosition + 1 < $iLength * 2; $i+=2) {
54 $oList->addListComponent($aStack[$i]);
55 }
56 array_splice($aStack, $iStartPosition - 1, $iLength * 2 - 1, array($oList));
57 }
58 }
59 if (!isset($aStack[0])) {
60 throw new UnexpectedTokenException(" {$oParserState->peek()} ", $oParserState->peek(1, -1) . $oParserState->peek(2), 'literal', $oParserState->currentLine());
61 }
62 return $aStack[0];
63 }
64
65 public static function parseIdentifierOrFunction(ParserState $oParserState, $bIgnoreCase = false) {
66 $sResult = $oParserState->parseIdentifier($bIgnoreCase);
67
68 if ($oParserState->comes('(')) {
69 $oParserState->consume('(');
70 $aArguments = Value::parseValue($oParserState, array('=', ' ', ','));
71 $sResult = new CSSFunction($sResult, $aArguments, ',', $oParserState->currentLine());
72 $oParserState->consume(')');
73 }
74
75 return $sResult;
76 }
77
78 public static function parsePrimitiveValue(ParserState $oParserState) {
79 $oValue = null;
80 $oParserState->consumeWhiteSpace();
81 if (is_numeric($oParserState->peek()) || ($oParserState->comes('-.') && is_numeric($oParserState->peek(1, 2))) || (($oParserState->comes('-') || $oParserState->comes('.')) && is_numeric($oParserState->peek(1, 1)))) {
82 $oValue = Size::parse($oParserState);
83 } else if ($oParserState->comes('#') || $oParserState->comes('rgb', true) || $oParserState->comes('hsl', true)) {
84 $oValue = Color::parse($oParserState);
85 } else if ($oParserState->comes('url', true)) {
86 $oValue = URL::parse($oParserState);
87 } else if ($oParserState->comes('calc', true) || $oParserState->comes('-webkit-calc', true) || $oParserState->comes('-moz-calc', true)) {
88 $oValue = CalcFunction::parse($oParserState);
89 } else if ($oParserState->comes("'") || $oParserState->comes('"')) {
90 $oValue = CSSString::parse($oParserState);
91 } else if ($oParserState->comes("progid:") && $oParserState->getSettings()->bLenientParsing) {
92 $oValue = self::parseMicrosoftFilter($oParserState);
93 } else if ($oParserState->comes("[")) {
94 $oValue = LineName::parse($oParserState);
95 } else if ($oParserState->comes("U+")) {
96 $oValue = self::parseUnicodeRangeValue($oParserState);
97 } else {
98 $oValue = self::parseIdentifierOrFunction($oParserState);
99 }
100 $oParserState->consumeWhiteSpace();
101 return $oValue;
102 }
103
104 private static function parseMicrosoftFilter(ParserState $oParserState) {
105 $sFunction = $oParserState->consumeUntil('(', false, true);
106 $aArguments = Value::parseValue($oParserState, array(',', '='));
107 return new CSSFunction($sFunction, $aArguments, ',', $oParserState->currentLine());
108 }
109
110 private static function parseUnicodeRangeValue(ParserState $oParserState) {
111 $iCodepointMaxLenth = 6; // Code points outside BMP can use up to six digits
112 $sRange = "";
113 $oParserState->consume("U+");
114 do {
115 if ($oParserState->comes('-')) $iCodepointMaxLenth = 13; // Max length is 2 six digit code points + the dash(-) between them
116 $sRange .= $oParserState->consume(1);
117 } while (strlen($sRange) < $iCodepointMaxLenth && preg_match("/[A-Fa-f0-9\?-]/", $oParserState->peek()));
118 return "U+{$sRange}";
119 }
120
121 /**
122 * @return int
123 */
124 public function getLineNo() {
125 return $this->iLineNo;
126 }
127
128 //Methods are commented out because re-declaring them here is a fatal error in PHP < 5.3.9
fbe18cc0
FM
129 //public abstract function __toString();
130 //public abstract function render(\Sabberworm\CSS\OutputFormat $oOutputFormat);
131}