Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
codyfinegan committed Apr 18, 2024
1 parent 022cbf1 commit c338a45
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 8 deletions.
135 changes: 127 additions & 8 deletions src/Compiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
use ScssPhp\ScssPhp\Logger\StreamLogger;
use ScssPhp\ScssPhp\Node\Number;
use ScssPhp\ScssPhp\SourceMap\SourceMapGenerator;
use ScssPhp\ScssPhp\Transforms\Resource;
use ScssPhp\ScssPhp\Transforms\ResourceFactory;
use ScssPhp\ScssPhp\Transforms\Transform;
use ScssPhp\ScssPhp\Util\Path;

/**
Expand Down Expand Up @@ -326,10 +329,8 @@ class Compiler
* The directory of the currently processed file
*
* @var string|null
*
* Changed to protected by Totara
*/
protected $currentDirectory;
private $currentDirectory;

/**
* The directory of the input file
Expand All @@ -353,6 +354,20 @@ class Compiler
*/
private $warnedChildFunctions = [];

/**
* @var array<string, Transform> Map of transformations
*/
private $transforms = [];

/**
* Optional file loader
*
* @var callable|null
*/
private $fileLoader = null;

private ?ResourceFactory $resourceFactory = null;

/**
* Constructor
*
Expand Down Expand Up @@ -5750,6 +5765,17 @@ public function addFeature($name)
*/
protected function importFile($path, OutputBlock $out)
{
$originalPath = $path;
$pos = strrpos($path, '!');
$transforms = [];

if ($pos !== false) {
$path = substr($path, $pos + 1);
if ($pos !== 0) {
$transforms = explode('!', substr($path, 0, $pos));
}
}

$this->pushCallStack('import ' . $this->getPrettyPath($path));
// see if tree is cached
$realPath = realpath($path);
Expand All @@ -5758,6 +5784,8 @@ protected function importFile($path, OutputBlock $out)
$realPath = $path;
}

$cacheKey = ($transforms ? implode('!', $transforms) : '') . $realPath;

if (substr($path, -5) === '.sass') {
$this->sourceIndex = \count($this->sourceNames);
$this->sourceNames[] = $path;
Expand All @@ -5767,16 +5795,33 @@ protected function importFile($path, OutputBlock $out)
throw $this->error('The Sass indented syntax is not implemented.');
}

if (isset($this->importCache[$realPath])) {
if (isset($this->importCache[$cacheKey])) {
$this->handleImportLoop($realPath);

$tree = $this->importCache[$realPath];
$tree = $this->importCache[$cacheKey];
} else {
$code = file_get_contents($path);
// Allow the custom file loaders
if ($this->fileLoader !== null) {
$code = call_user_func($this->fileLoader, $path);
} else {
$code = file_get_contents($path);
}

$parser = $this->parserFactory($path);
$tree = $parser->parse($code);

$this->importCache[$realPath] = $tree;
// Apply webpack-style transforms to the tree
if ($transforms) {
$factory = ($this->resourceFactory ?? new ResourceFactory());

// A resource holds the ast tree & code, and is passed across the transforms
$resource = $factory->createResource($path, $tree, $code);

Check failure on line 5818 in src/Compiler.php

View workflow job for this annotation

GitHub Actions / Static analysis

Parameter #2 $code of method ScssPhp\ScssPhp\Transforms\ResourceFactory::createResource() expects string, ScssPhp\ScssPhp\Block given.

// The resource is transformed and the modified tree is returned
$tree = $this->executeTransforms($transforms, $resource);
}

$this->importCache[$cacheKey] = $tree;
}

$currentDirectory = $this->currentDirectory;
Expand Down Expand Up @@ -5819,7 +5864,9 @@ public static function isCssImport($url)
}

/**
* Return the file path for an import url if it exists
* Return the file path for an import url if it exists.
*
* This includes an override supporting webkit transformations.
*
* @internal
*
Expand All @@ -5829,6 +5876,32 @@ public static function isCssImport($url)
* @return string|null
*/
public function findImport($url, $currentDir = null)
{
$pos = strrpos($url, '!');
if ($pos !== false) {
$transforms = substr($url, 0, $pos);
$path = substr($url, $pos + 1);
$result = $this->doFindImport($path, $currentDir);
if ($result === null) {
throw $this->error("`$path` file not found for @import");
}
return "$transforms!$result";
}

return $this->doFindImport($url, $currentDir);
}

/**
* The original find import command
*
* @internal
*
* @param string $url
* @param string|null $currentDir
*
* @return string|null
*/
private function doFindImport($url, $currentDir = null)
{
// Vanilla css and external requests. These are not meant to be Sass imports.
// Callback importers are still called for BC.
Expand Down Expand Up @@ -10472,4 +10545,50 @@ protected function libScssphpGlob($args)

return [Type::T_LIST, ',', $listParts];
}

/**
* @param string $name
* @param Transform $transform
* @return void
*/
public function registerTransform(string $name, Transform $transform): void {
$this->transforms[$name] = $transform;
}

/**
* Set the file loader.
*
* @param callable|null $fileLoader
* @return void
*/
public function setFileLoader(?callable $fileLoader): void {
$this->fileLoader = $fileLoader;
}

/**
* @param ResourceFactory|null $factory
* @return void
*/
public function setResourceFactory(?ResourceFactory $factory): void {
$this->resourceFactory = $factory;
}

/**
* @param array $transforms
* @param Resource $resource
* @return Block
* @throws \Exception
*/
protected function executeTransforms(array $transforms, Resource $resource): Block {

Check failure on line 10582 in src/Compiler.php

View workflow job for this annotation

GitHub Actions / Static analysis

Method ScssPhp\ScssPhp\Compiler::executeTransforms() has parameter $transforms with no value type specified in iterable type array.
// transforms execute from right to left (like webpack)
$transforms = array_reverse($transforms, true);
foreach ($transforms as $name => $transform) {
if (!isset($this->transforms[$name])) {
throw new \Exception('Unknown transform "' . $name . '"');
}
$this->transforms[$name]->execute($resource);
}

return $resource->getAst();
}
}
43 changes: 43 additions & 0 deletions src/Transforms/Resource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace ScssPhp\ScssPhp\Transforms;

use ScssPhp\ScssPhp\Block;

/**
* A resource represents the scss file that is in the process of transforming.
*/
class Resource {
private bool $modified = false;

public function __construct(protected string $path, protected Block $ast, protected string $code) {

}

/**
* Return the modified Tree
*
* @return Block
*/
public function getAst(): Block {
return $this->ast;
}

/**
* Marks the AST has been modified
*
* @return void
*/
public function markASTModified(): void {
$this->modified = true;
}

/**
* Indicates if the resource AST has been modified or not.
*
* @return bool
*/
public function isASTOnly(): bool {
return $this->modified;
}
}
19 changes: 19 additions & 0 deletions src/Transforms/ResourceFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace ScssPhp\ScssPhp\Transforms;

use ScssPhp\ScssPhp\Block;

class ResourceFactory {
/**
* Create a new resource instance to be used in transformations.
*
* @param string $path
* @param string $code
* @param Block $ast
* @return Resource
*/
public function createResource(string $path, string $code, Block $ast): Resource {
return new Resource($path, $ast, $code);
}
}
11 changes: 11 additions & 0 deletions src/Transforms/Transform.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace ScssPhp\ScssPhp\Transforms;

interface Transform {
/**
* @param Resource $resource
* @return void
*/
public function execute(\ScssPhp\ScssPhp\Transforms\Resource $resource): void;
}
Empty file.

0 comments on commit c338a45

Please sign in to comment.