Skip to content

[AssetMapper] add "full" type for packages to download all content #60545

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: 7.4
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Symfony/Component/AssetMapper/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
CHANGELOG
=========

7.4
---

* Add "full" type for a package to download all files

7.3
---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntries;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntry;
use Symfony\Component\AssetMapper\ImportMap\ImportMapManager;
use Symfony\Component\AssetMapper\ImportMap\ImportMapType;
use Symfony\Component\AssetMapper\ImportMap\ImportMapVersionChecker;
use Symfony\Component\AssetMapper\ImportMap\PackageRequireOptions;
use Symfony\Component\Console\Attribute\AsCommand;
Expand Down Expand Up @@ -51,6 +52,7 @@ protected function configure(): void
->addArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'The packages to add')
->addOption('entrypoint', null, InputOption::VALUE_NONE, 'Make the packages an entrypoint?')
->addOption('path', null, InputOption::VALUE_REQUIRED, 'The local path where the package lives relative to the project root')
->addOption('type', null, InputOption::VALUE_REQUIRED, 'The package type, specified for specific download.')
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Simulate the installation of the packages')
->setHelp(<<<'EOT'
The <info>%command.name%</info> command adds packages to <comment>importmap.php</comment> usually
Expand Down Expand Up @@ -124,6 +126,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$parts['alias'] ?? null,
$path,
$input->getOption('entrypoint'),
$input->getOption('type') ? ImportMapType::tryfrom($input->getOption('type')) : null,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ public function requirePackages(array $packagesToRequire, ImportMapEntries $impo

$newEntry = ImportMapEntry::createLocal(
$requireOptions->importName,
self::getImportMapTypeFromFilename($requireOptions->path),
$requireOptions->importMapType ?? self::getImportMapTypeFromFilename($requireOptions->path),
$path,
$requireOptions->entrypoint,
);
Expand Down
11 changes: 11 additions & 0 deletions src/Symfony/Component/AssetMapper/ImportMap/ImportMapType.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,15 @@ enum ImportMapType: string
{
case JS = 'js';
case CSS = 'css';
case FULL = 'full';

public function hasMainFile(): bool
{
if($this == self::FULL)
{
return false;
}

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public function __construct(
?string $importName = null,
public readonly ?string $path = null,
public readonly bool $entrypoint = false,
public readonly ?ImportMapType $importMapType = null,
) {
$this->importName = $importName ?: $packageModuleSpecifier;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ public function downloadPackages(?callable $progressCallback = null): array
throw new \LogicException(\sprintf('The package "%s" was not downloaded.', $package));
}

$this->remotePackageStorage->save($entry, $contents[$package]['content']);
if($contents[$package]['hasMainFile']) {
$this->remotePackageStorage->save($entry, $contents[$package]['content']);
}

foreach ($contents[$package]['extraFiles'] as $extraFilename => $extraFileContents) {
$this->remotePackageStorage->saveExtraFile($entry, $extraFilename, $extraFileContents);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ final class JsDelivrEsmResolver implements PackageResolverInterface
public const URL_PATTERN_DIST_CSS = 'https://cdn.jsdelivr.net/npm/%s@%s%s';
public const URL_PATTERN_DIST = self::URL_PATTERN_DIST_CSS.'/+esm';
public const URL_PATTERN_ENTRYPOINT = 'https://data.jsdelivr.com/v1/packages/npm/%s@%s/entrypoints';
public const URL_PATTERN_FULL_DOWNLOAD = 'https://data.jsdelivr.com/v1/packages/npm/%s@%s';

public const IMPORT_REGEX = '#(?:import\s*(?:[\w$]+,)?(?:(?:\{[^}]*\}|[\w$]+|\*\s*as\s+[\w$]+)\s*\bfrom\s*)?|export\s*(?:\{[^}]*\}|\*)\s*from\s*|await\simport\()("/npm/((?:@[^/]+/)?[^@]+?)(?:@([^/]+))?((?:/[^/]+)*?)/\+esm")(?:\)*)#';

Expand Down Expand Up @@ -80,7 +81,7 @@ public function resolvePackages(array $packagesToRequire): array
throw new RuntimeException(\sprintf('Unable to find the latest version for package "%s" - try specifying the version manually.', $packageName));
}

$pattern = $this->resolveUrlPattern($packageName, $filePath);
$pattern = $this->resolveUrlPattern($packageName, $filePath, $options->importMapType);
$requiredPackages[$i][1] = $this->httpClient->request('GET', \sprintf($pattern, $packageName, $version, $filePath));
$requiredPackages[$i][4] = $version;

Expand Down Expand Up @@ -108,7 +109,7 @@ public function resolvePackages(array $packagesToRequire): array
}

$contentType = $response->getHeaders()['content-type'][0] ?? '';
$type = str_starts_with($contentType, 'text/css') ? ImportMapType::CSS : ImportMapType::JS;
$type = $options->importMapType ?? (str_starts_with($contentType, 'text/css') ? ImportMapType::CSS : ImportMapType::JS);
$resolvedPackages[$options->packageModuleSpecifier] = new ResolvedImportMapPackage($options, $version, $type);

$packagesToRequire = array_merge($packagesToRequire, $this->fetchPackageRequirementsFromImports($response->getContent()));
Expand Down Expand Up @@ -201,6 +202,7 @@ public function downloadPackages(array $importMapEntries, ?callable $progressCal
'content' => $this->makeImportsBare($response->getContent(), $dependencies, $extraFiles, $entry->type, $entry->getPackagePathString()),
'dependencies' => $dependencies,
'extraFiles' => [],
'hasMainFile' => $entry->type->hasMainFile(),
];

if (0 !== \count($extraFiles)) {
Expand Down Expand Up @@ -317,6 +319,24 @@ private function makeImportsBare(string $content, array &$dependencies, array &$
return $content;
}

if (ImportMapType::FULL === $type) {
$data = json_decode($content);
$getFiles = function ($section, string $path) use(&$getFiles, &$extraFiles) {
foreach($section as $item) {
if($item->type == 'file') {
$extraFiles[] = $path . $item->name;
}
if($item->type == 'directory') {
$getFiles($item->files, $path . $item->name . '/' );
}
}
};

$getFiles($data->files, '/');

return $content;
}

preg_match_all(CssAssetUrlCompiler::ASSET_URL_PATTERN, $content, $matches);
foreach ($matches[1] as $path) {
if (str_starts_with($path, 'data:')) {
Expand Down Expand Up @@ -345,6 +365,10 @@ private function resolveUrlPattern(string $packageName, string $path, ?ImportMap
return self::URL_PATTERN_DIST_CSS;
}

if (ImportMapType::FULL === $type) {
return self::URL_PATTERN_FULL_DOWNLOAD;
}

return self::URL_PATTERN_DIST;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function resolvePackages(array $packagesToRequire): array;
*
* @param array<string, ImportMapEntry> $importMapEntries
*
* @return array<string, array{content: string, dependencies: string[], extraFiles: array<string, string>}>
* @return array<string, array{content: string, dependencies: string[], extraFiles: array<string, string>, hasMainFile: bool}>
*/
public function downloadPackages(array $importMapEntries, ?callable $progressCallback = null): array;
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ public function testDownloadPackagesDownloadsEverythingWithNoInstalled()
$progressCallback
)
->willReturn([
'foo' => ['content' => 'foo content', 'dependencies' => [], 'extraFiles' => ['/path/to/extra-file.woff' => 'extra file contents']],
'bar.js/file' => ['content' => 'bar content', 'dependencies' => [], 'extraFiles' => []],
'baz' => ['content' => 'baz content', 'dependencies' => ['foo'], 'extraFiles' => []],
'different_specifier' => ['content' => 'different content', 'dependencies' => [], 'extraFiles' => []],
'foo' => ['content' => 'foo content', 'dependencies' => [], 'extraFiles' => ['/path/to/extra-file.woff' => 'extra file contents'], 'hasMainFile' => true],
'bar.js/file' => ['content' => 'bar content', 'dependencies' => [], 'extraFiles' => [], 'hasMainFile' => true],
'baz' => ['content' => 'baz content', 'dependencies' => ['foo'], 'extraFiles' => [], 'hasMainFile' => true],
'different_specifier' => ['content' => 'different content', 'dependencies' => [], 'extraFiles' => [], 'hasMainFile' => true],
]);

$downloader = new RemotePackageDownloader(
Expand Down Expand Up @@ -131,9 +131,9 @@ public function testPackagesWithCorrectInstalledVersionSkipped()
$packageResolver->expects($this->once())
->method('downloadPackages')
->willReturn([
'bar.js/file' => ['content' => 'new bar content', 'dependencies' => [], 'extraFiles' => []],
'baz' => ['content' => 'new baz content', 'dependencies' => [], 'extraFiles' => []],
'has-missing-extra' => ['content' => 'new content', 'dependencies' => [], 'extraFiles' => ['/path/to/extra-file.woff' => 'extra file contents']],
'bar.js/file' => ['content' => 'new bar content', 'dependencies' => [], 'extraFiles' => [], 'hasMainFile' => true],
'baz' => ['content' => 'new baz content', 'dependencies' => [], 'extraFiles' => [], 'hasMainFile' => true],
'has-missing-extra' => ['content' => 'new content', 'dependencies' => [], 'extraFiles' => ['/path/to/extra-file.woff' => 'extra file contents'], 'hasMainFile' => true],
]);

$downloader = new RemotePackageDownloader(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ public static function provideDownloadPackagesTests()
],
],
[
'lodash' => ['content' => 'lodash contents', 'dependencies' => [], 'extraFiles' => []],
'lodash' => ['content' => 'lodash contents', 'dependencies' => [], 'extraFiles' => [], 'hasMainFile' => true],
],
];

Expand All @@ -318,7 +318,7 @@ public static function provideDownloadPackagesTests()
],
],
[
'lodash' => ['content' => 'lodash contents', 'dependencies' => [], 'extraFiles' => []],
'lodash' => ['content' => 'lodash contents', 'dependencies' => [], 'extraFiles' => [], 'hasMainFile' => true],
],
];

Expand All @@ -331,7 +331,7 @@ public static function provideDownloadPackagesTests()
],
],
[
'lodash' => ['content' => 'chart.js contents', 'dependencies' => [], 'extraFiles' => []],
'lodash' => ['content' => 'chart.js contents', 'dependencies' => [], 'extraFiles' => [], 'hasMainFile' => true],
],
];

Expand All @@ -344,7 +344,7 @@ public static function provideDownloadPackagesTests()
],
],
[
'lodash' => ['content' => 'bootstrap.css contents', 'dependencies' => [], 'extraFiles' => []],
'lodash' => ['content' => 'bootstrap.css contents', 'dependencies' => [], 'extraFiles' => [], 'hasMainFile' => true],
],
];

Expand All @@ -369,9 +369,9 @@ public static function provideDownloadPackagesTests()
],
],
[
'lodash' => ['content' => 'lodash contents', 'dependencies' => [], 'extraFiles' => []],
'chart.js/auto' => ['content' => 'chart.js contents', 'dependencies' => [], 'extraFiles' => []],
'bootstrap/dist/bootstrap.css' => ['content' => 'bootstrap.css contents', 'dependencies' => [], 'extraFiles' => []],
'lodash' => ['content' => 'lodash contents', 'dependencies' => [], 'extraFiles' => [], 'hasMainFile' => true],
'chart.js/auto' => ['content' => 'chart.js contents', 'dependencies' => [], 'extraFiles' => [], 'hasMainFile' => true],
'bootstrap/dist/bootstrap.css' => ['content' => 'bootstrap.css contents', 'dependencies' => [], 'extraFiles' => [], 'hasMainFile' => true],
],
];

Expand All @@ -390,6 +390,7 @@ public static function provideDownloadPackagesTests()
'content' => 'import{Color as t}from"@kurkle/color";function e(){}const i=(()=',
'dependencies' => ['@kurkle/color'],
'extraFiles' => [],
'hasMainFile' => true,
],
],
];
Expand All @@ -409,6 +410,7 @@ public static function provideDownloadPackagesTests()
'content' => 'import e from"locutus/php/strings/sprintf";console.log()',
'dependencies' => ['locutus/php/strings/sprintf'],
'extraFiles' => [],
'hasMainFile' => true,
],
],
];
Expand All @@ -429,6 +431,7 @@ public static function provideDownloadPackagesTests()
'content' => 'as Ticks,ta as TimeScale,ia as TimeSeriesScale,oo as Title,wo as Tooltip,Ci as _adapters,us as _detectPlatform,Ye as animator,Si as controllers,tn as default,St as defaults,Pn as elements,qi as layouts,ko as plugins,na as registerables,Ps as registry,sa as scales};',
'dependencies' => [],
'extraFiles' => [],
'hasMainFile' => true,
],
],
];
Expand All @@ -453,6 +456,7 @@ public static function provideDownloadPackagesTests()
EOF,
'dependencies' => [],
'extraFiles' => [],
'hasMainFile' => true,
],
],
];
Expand All @@ -471,6 +475,7 @@ public static function provideDownloadPackagesTests()
'content' => 'print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}}',
'dependencies' => [],
'extraFiles' => [],
'hasMainFile' => true,
],
],
];
Expand Down
Loading