PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/mishal-iless/lib/ILess/Context.php

https://github.com/ratbird/hope
PHP | 492 lines | 194 code | 69 blank | 229 comment | 8 complexity | 07b135586830663d19fe14eb3eb7f7cd MD5 | raw file
Possible License(s): LGPL-2.1, CC-BY-SA-3.0, MIT, BSD-3-Clause, GPL-2.0
  1. <?php
  2. /*
  3. * This file is part of the ILess
  4. *
  5. * For the full copyright and license information, please view the LICENSE
  6. * file that was distributed with this source code.
  7. */
  8. namespace ILess;
  9. use ILess\Node;
  10. use ILess\Node\RulesetNode;
  11. use ILess\Util;
  12. use InvalidArgumentException;
  13. /**
  14. * Context
  15. *
  16. * @package ILess
  17. */
  18. class Context
  19. {
  20. /**
  21. * Array of frames
  22. *
  23. * @var array
  24. */
  25. public $frames = [];
  26. /**
  27. * Custom variables
  28. *
  29. * @var RulesetNode
  30. */
  31. public $customVariables;
  32. /**
  33. * Compress the output?
  34. *
  35. * @var bool
  36. */
  37. public $compress = false;
  38. /**
  39. * Can shorten colors?
  40. *
  41. * @var boolean
  42. */
  43. public $canShortenColors = true;
  44. /**
  45. * The math precision
  46. *
  47. * @var integer
  48. */
  49. public $numPrecision = null;
  50. /**
  51. * @var boolean
  52. */
  53. public $strictImports = false;
  54. /**
  55. * Adjust URL's to be relative?
  56. *
  57. * @var boolean
  58. */
  59. public $relativeUrls = false;
  60. /**
  61. * Root path
  62. *
  63. * @var string
  64. */
  65. public $rootPath;
  66. /**
  67. * @var array
  68. */
  69. public $mediaBlocks = [];
  70. /**
  71. * @var array
  72. */
  73. public $mediaPath = [];
  74. /**
  75. * @var array
  76. */
  77. public $paths = [];
  78. /**
  79. * Math is required to be in parenthesis like: <pre>(1+1)</pre>
  80. *
  81. * @var boolean
  82. */
  83. public $strictMath = true;
  84. /**
  85. * Validate the units used?
  86. *
  87. * @var boolean
  88. */
  89. public $strictUnits = true;
  90. /**
  91. * Process imports?
  92. *
  93. * @var boolean
  94. */
  95. public $processImports = true;
  96. /**
  97. * IE8 data-uri compatibility
  98. *
  99. * @var boolean
  100. */
  101. public $ieCompat = true;
  102. /**
  103. * Dump line numbers?
  104. *
  105. * @var false|string all|comment|mediaquery
  106. */
  107. public $dumpLineNumbers = false;
  108. /**
  109. * Tab level
  110. *
  111. * @var integer
  112. */
  113. public $tabLevel = 0;
  114. /**
  115. * First selector flag
  116. *
  117. * @var boolean
  118. */
  119. public $firstSelector = false;
  120. /**
  121. * Last rule flag
  122. *
  123. * @var boolean
  124. */
  125. public $lastRule = false;
  126. /**
  127. * Important flag (currently not implemented in less.js)
  128. *
  129. * @var boolean
  130. */
  131. public $isImportant = false;
  132. /**
  133. * Selectors
  134. *
  135. * @var array
  136. */
  137. public $selectors = [];
  138. /**
  139. * Parens stack
  140. *
  141. * @var array
  142. */
  143. protected $parensStack = [];
  144. /**
  145. * Current file information. For error reporting,
  146. * importing and making urls relative etc.
  147. *
  148. * @var FileInfo
  149. */
  150. public $currentFileInfo;
  151. /**
  152. * What is this for?
  153. *
  154. * @var boolean
  155. */
  156. public $importMultiple = false;
  157. /**
  158. * Source map flag
  159. *
  160. * @var boolean
  161. */
  162. public $sourceMap = false;
  163. /**
  164. * Array of source map options
  165. *
  166. * @var array
  167. */
  168. public $sourceMapOptions = [];
  169. /**
  170. * Filename to contents of all parsed the files
  171. *
  172. * @var array
  173. */
  174. public $contentsMap = [];
  175. /**
  176. * The function registry
  177. *
  178. * @var FunctionRegistry
  179. */
  180. protected $functionRegistry;
  181. /**
  182. * Used to bubble up !important statements
  183. *
  184. * @var array
  185. */
  186. public $importantScope = [];
  187. /**
  188. * Whether to add args into url tokens
  189. *
  190. * @var string
  191. */
  192. public $urlArgs = '';
  193. /**
  194. * Constructor
  195. *
  196. * @param FunctionRegistry $registry The function registry
  197. * @param array $options
  198. * @throws InvalidArgumentException If passed options are invalid
  199. */
  200. public function __construct(array $options = [], FunctionRegistry $registry = null)
  201. {
  202. if ($registry) {
  203. $this->setFunctionRegistry($registry);
  204. }
  205. $invalid = [];
  206. // underscored property names
  207. $properties = array_keys(get_class_vars(__CLASS__));
  208. $properties = array_combine($properties, $properties);
  209. $properties = array_change_key_case(array_flip(preg_replace('/((?<=[a-z]|\d)[A-Z]|(?<!^)[A-Z](?=[a-z]))/',
  210. '_\\1', $properties)));
  211. foreach ($options as $option => $value) {
  212. if (isset($properties[$option])) {
  213. $option = $properties[$option];
  214. } elseif (!property_exists($this, $option)) {
  215. $invalid[] = $option;
  216. continue;
  217. }
  218. switch ($option) {
  219. case 'dumpLineNumbers':
  220. if (!in_array($value, [
  221. true,
  222. DebugInfo::FORMAT_ALL,
  223. DebugInfo::FORMAT_COMMENT,
  224. DebugInfo::FORMAT_MEDIA_QUERY,
  225. ], true)
  226. ) {
  227. // FIXME: report possible values?
  228. $invalid[] = $option;
  229. }
  230. break;
  231. case 'strictUnits':
  232. case 'compress':
  233. case 'importMultiple':
  234. case 'ieCompat':
  235. $value = (boolean)$value;
  236. break;
  237. }
  238. $this->$option = $value;
  239. }
  240. if (count($invalid)) {
  241. throw new InvalidArgumentException(sprintf('Invalid options "%s" given.', join(', ', $invalid)));
  242. }
  243. }
  244. /**
  245. * Returns the function registry
  246. *
  247. * @return FunctionRegistry
  248. */
  249. public function getFunctionRegistry()
  250. {
  251. return $this->functionRegistry;
  252. }
  253. /**
  254. * Returns the contents map
  255. *
  256. * @return array
  257. */
  258. public function getContentsMap()
  259. {
  260. return $this->contentsMap;
  261. }
  262. /**
  263. * Sets file contents to the map
  264. *
  265. * @param string $filePath
  266. * @param string $content
  267. * @return Context
  268. */
  269. public function setFileContent($filePath, $content)
  270. {
  271. $this->contentsMap[$filePath] = $content;
  272. return $this;
  273. }
  274. /**
  275. * Sets the function registry, also links the registry with this environment instance
  276. *
  277. * @param FunctionRegistry $registry
  278. * @return Context
  279. */
  280. public function setFunctionRegistry(FunctionRegistry $registry)
  281. {
  282. $this->functionRegistry = $registry;
  283. // provide access to The context, which is need to access generateCSS()
  284. $this->functionRegistry->setEnvironment($this);
  285. return $this;
  286. }
  287. /**
  288. * Sets current file
  289. *
  290. * @param string $file The path to a file
  291. */
  292. public function setCurrentFile($file)
  293. {
  294. $file = Util::normalizePath($file);
  295. $dirname = preg_replace('/[^\/\\\\]*$/', '', $file);
  296. $this->currentFileInfo = new FileInfo([
  297. 'currentDirectory' => $dirname,
  298. 'filename' => $file,
  299. 'rootPath' => $this->currentFileInfo && $this->currentFileInfo->rootPath ?
  300. $this->currentFileInfo->rootPath : $this->rootPath,
  301. 'entryPath' => $dirname,
  302. ]);
  303. }
  304. /**
  305. * Creates a copy of The context
  306. *
  307. * @param Context $context
  308. * @param array $frames
  309. * @return Context
  310. */
  311. public static function createCopy(Context $context, array $frames = [])
  312. {
  313. // what to copy?
  314. $copyProperties = [
  315. // options
  316. 'compress', // whether to compress
  317. 'canShortenColors', // can shorten colors?
  318. 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
  319. 'strictMath', // whether math has to be within parenthesis
  320. 'strictUnits', // whether units need to evaluate correctly
  321. 'sourceMap', // whether to output a source map
  322. 'sourceMapOptions', // options for source map generator
  323. 'importMultiple', // whether we are currently importing multiple copies,
  324. 'relativeUrls', // adjust relative urls?,
  325. 'rootPath', // root path
  326. 'dumpLineNumbers', // dump line numbers?
  327. 'contentsMap', // filename to contents of all the files
  328. 'urlArgs', // whether to add args into url tokens
  329. 'customVariables', // variables from the php API
  330. 'currentFileInfo', // current file information object
  331. 'importantScope', // current file information object
  332. ];
  333. $target = new Context([], $context->getFunctionRegistry());
  334. self::copyFromOriginal($context, $target, $copyProperties);
  335. $target->frames = $frames;
  336. return $target;
  337. }
  338. /**
  339. * @param Context $context
  340. * @param array $frames
  341. * @return Context
  342. */
  343. public static function createCopyForCompilation(Context $context, array $frames = [])
  344. {
  345. $copyProperties = [
  346. 'compress', // whether to compress
  347. 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
  348. 'strictMath', // whether math has to be within parenthesis
  349. 'strictUnits', // whether units need to evaluate correctly
  350. 'sourceMap', // whether to output a source map
  351. 'importMultiple', // whether we are currently importing multiple copies
  352. 'dumpLineNumbers', // dump line numbers?
  353. 'urlArgs', // whether to add args into url tokens
  354. 'importantScope', // used to bubble up !important statements
  355. 'customVariables', // variables from the php API
  356. ];
  357. $target = new Context([], $context->getFunctionRegistry());
  358. self::copyFromOriginal($context, $target, $copyProperties);
  359. $target->frames = $frames;
  360. return $target;
  361. }
  362. private static function copyFromOriginal(Context $original, Context $targetEnv, $copyProperties)
  363. {
  364. foreach ($copyProperties as $property) {
  365. if (property_exists($original, $property)) {
  366. $targetEnv->$property = $original->$property;
  367. }
  368. }
  369. }
  370. /**
  371. * Is math on?
  372. *
  373. * @return boolean
  374. */
  375. public function isMathOn()
  376. {
  377. return $this->strictMath ? ($this->parensStack && count($this->parensStack)) : true;
  378. }
  379. /**
  380. * @return Context
  381. */
  382. public function inParenthesis()
  383. {
  384. $this->parensStack[] = true;
  385. return $this;
  386. }
  387. /**
  388. * @return Context
  389. */
  390. public function outOfParenthesis()
  391. {
  392. array_pop($this->parensStack);
  393. return $this;
  394. }
  395. /**
  396. * @param Node $frame
  397. */
  398. public function unshiftFrame($frame)
  399. {
  400. array_unshift($this->frames, $frame);
  401. }
  402. /**
  403. * @return array
  404. */
  405. public function shiftFrame()
  406. {
  407. return array_shift($this->frames);
  408. }
  409. /**
  410. * @param array $frame
  411. */
  412. public function addFrame($frame)
  413. {
  414. $this->frames[] = $frame;
  415. }
  416. /**
  417. * @param array $frames
  418. */
  419. public function addFrames(array $frames)
  420. {
  421. $this->frames = array_merge($this->frames, $frames);
  422. }
  423. }