Skip to content
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

Feature Request: Add relativePath or themePath to Asset #227

Closed
3 tasks done
strarsis opened this issue May 20, 2022 · 9 comments · Fixed by #237
Closed
3 tasks done

Feature Request: Add relativePath or themePath to Asset #227

strarsis opened this issue May 20, 2022 · 9 comments · Fixed by #237
Labels
enhancement New feature or request

Comments

@strarsis
Copy link
Contributor

Terms

Summary

Asset currently has a path() function that returns the full, absolute path to the asset.
Sometimes the path relative to the theme directory is also needed, as for add_editor_style.
Currently, additional code/library is needed to get the path relative to theme directory from the absolute path returned by the path() function.
It would be nice if also a function is added that returns the path to asset relative to the (Sage) theme directory.

Motivation

Why are we doing this?

Sometimes the path relative to the theme directory is also needed.

What use cases does it support?

add_editor_style requires either an URI (that currently cause an issue post-processing CSS in Gutenberg editor to rewrite URLs relative to stylehsheet) or a path to a local file relative to the theme directory (that doesn't cause this issue).

What is the expected outcome?

Elimination of additional code/library for making the absolute asset path (from path()) relative to the theme directory path,
so it can be used by functions like add_editor_style.

Potential conflicts / foreseeable issues

One more API function in acorn, paths and their handling shouldn't change in the foreseeable future, so once the code (and tests) for a theme-directory-relative path function is in place, no changes should be expected any time soon.
As this functionality would be requires in any theme that adds the frontend styles in the expected way (using add_editor_style), this should justify adding such an additional function.

Additional Context

https://discourse.roots.io/t/absolute-domain-relative-path-for-asset-urls-in-css/23121/4

@strarsis strarsis added the enhancement New feature or request label May 20, 2022
@QWp6t
Copy link
Sponsor Member

QWp6t commented May 20, 2022

Assets don't know what a theme is and have no direct relation to the theme. So I'm unlikely to add that sort of logic directly into the asset object. But I'm not opposed to determining the relative path to the asset from the manifest (which is <theme>/public), since that's already determined.

I'll give it a bit of a think, but in the meantime, you can use something like this:

app('files')->getRelativePath(get_theme_file_path(), $asset->path());

@strarsis
Copy link
Contributor Author

@QWp6t: Excellent point! The Asset represents an asset file, but should and has no idea of themes, it could be used in a plugin, outside of WordPress, etc.

The approach with app(...)->getRelativePath(...) already looks clean and logical.

@strarsis
Copy link
Contributor Author

@QWp6t: app('files') returns an Illuminate\Filesystem\Filesystem instance, not a Roots\Acorn\Filesystem\Filesystem one (that extends the Illuminate class with functions as the getRelativePath function):
Uncaught BadMethodCallException: Method Illuminate\Filesystem\Filesystem::getRelativePath does not exist. in [...]/themes/[...]/vendor/illuminate/macroable/Traits/Macroable.php:113

@strarsis
Copy link
Contributor Author

@QWp6t: For now I solved this by instantiating the returned Illuminate\Filesystem\Filesystem as a Roots\Acorn\Filesystem\Filesystem instance:

add_action('after_setup_theme', function () {
    $fs  = app('files');
    $afs = new \Roots\Acorn\Filesystem\Filesystem($fs);
    $asset = asset('app.css');
    $relCssPath = $afs->getRelativePath(get_template_directory(), $asset->path());
    add_editor_style($relCssPath);
});

However, the getRelativePath function, that originally came from symfony/routing (as @linked in the comment of that function) doesn't resolve the relative path correctly - the theme directory itself is also in the returned path:
Expected: public/app.a2287c.css
Actual: the-theme-folder/public/app.a2287c.css

The most recent function of Symfony to get a relative path is makePathRelative.
But it has its own issues, notably with paths that don't end with a slash (as this path to the CSS file):
symfony/symfony#40051

It may make sense using the Symfony relative path function and add a fix for paths that don't end with a slash for the Roots\Acorn\Filesystem\Filesystem getRelativePath function.

@QWp6t
Copy link
Sponsor Member

QWp6t commented Jun 26, 2022

Looks like there was a misconfiguration in 2.x, which I've addressed in #235 if you want to pull that in and test (or update your config/app.php file accordingly).

As for makeRelativePath() including the theme directory itself, I believe that has to do with whether you have a trailing slash in the base path.

- app('files')->getRelativePath(get_theme_file_path(), asset('app.css')->path())
+ app('files')->getRelativePath(trailingslashit(get_theme_file_path()), asset('app.css')->path())

(apologies for the ugly terminal lol)
image

Let me know if that works for you.

PS-
Do you happen to know what the difference is between Path::makeRelative() and Filesystem::makePathRelative()?

If you're unsure, no worries. I'm just a little curious.

@strarsis
Copy link
Contributor Author

strarsis commented Jun 26, 2022

@QWp6t:

Do you happen to know what the difference is between Path::makeRelative() and Filesystem::makePathRelative()?

Tests for Path::makeRelative(): https://github.com/symfony/symfony/blob/123b1651c4a7e219ba59074441badfac65525efe/src/Symfony/Component/Filesystem/Tests/PathTest.php#L588
Tests for Filesystem::makePathRelative():
https://github.com/symfony/symfony/blob/123b1651c4a7e219ba59074441badfac65525efe/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php#L1145

From the class names, Path is meant for paths in general while Filesystem contains filesystem-specific code.
Filesystem could do some I/O (or use a Path I/O abstraction object), but here only string manipulation is used.

Judging from both of their respective tests, except for these two points, they should be equal in their behavior.

@strarsis
Copy link
Contributor Author

strarsis commented Jun 27, 2022

@QWp6t: Yes, applying the PR branch fixes it:

"require": {
  "roots/acorn": "dev-227-use-acorn-filesystem"
}
<?php
namespace App;

use function Roots\asset;

add_action('after_setup_theme', function () {
    // Add frontend styles as editor styles
    // Must be added by relative path (not remote URI)
    // @see https://core.trac.wordpress.org/ticket/55728#ticket
    // @see https://github.com/roots/acorn/issues/227#issuecomment-1166613881
    $relCssPath = app('files')->getRelativePath(trailingslashit(get_theme_file_path()), asset('app.css')->path());
    add_editor_style($relCssPath);
});

A patch-level release of acorn would be great!

@QWp6t
Copy link
Sponsor Member

QWp6t commented Jul 8, 2022

Config option for Roots\Acorn\Filesystem\Filesystem fixed in Acorn v2.1.0

@strarsis
Copy link
Contributor Author

strarsis commented Jul 10, 2022

With the newly added Asset::relativePath function this can be even further simplified:

namespace App;

use function Roots\asset;

add_action('after_setup_theme', function () {
    // Add frontend styles as editor styles
    // Must be added by relative path (not remote URI)
    // (@see https://core.trac.wordpress.org/ticket/55728#ticket)
    $relCssPath = asset('app.css')->relativePath(get_theme_file_path());
    add_editor_style($relCssPath);
});

(Discourse discussion)

Great work @QWp6t, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants