Skip to content

Commit

Permalink
Merge pull request #1 from nickpoulos/0.1.0
Browse files Browse the repository at this point in the history
v0.1.0
  • Loading branch information
nickpoulos authored Jun 12, 2021
2 parents df20dd7 + d7f68ba commit 2f04e23
Show file tree
Hide file tree
Showing 6 changed files with 624 additions and 47 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

All notable changes to `laravel-svelte-direct` will be documented in this file.

## 0.1.0 - 2021-06-11

- Refactor the generated bootstrap JavaScript to use the `svelte-tag` package under the hood

- Replace custom @sveltedirect Blade directive with Laravel's built-in @stack('sveltedirect')

- Migrate Laravel Svelte Direct Mix from its own package into this one

- Improve Regex for tag matching

- Refactor the main ServiceProvider to have cleaner functions

- Added several tests for the rest of the ServiceProvider functions

## 0.0.1b - 2021-05-24

- Hotfix to add default values for class vars, was causing errors in some cases
Expand Down
31 changes: 11 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,23 @@ But I like eating my cake too, and so this little project was born.

## How?

This project consists of two pieces.
This package has two main pieces.

- Laravel Mix plugin installed via NPM
- Compiles Svelte components into bite-sized JS files
- Blade Pre-Compiler/Directive installed via Composer
- Scans Blade templates and loads the right bite sized component JS
- A Laravel Mix plugin that compiles each of your Svelte components into their own bite-sized JS files

- A Blade Pre-Compiler that scans Blade templates identifies your Svelte component tags, and loads the right component JS automatically

### Install Laravel Svelte Direct

### Install Laravel Svelte Direct JavaScript
```bash
npm install laravel-svelte-direct-mix
````
composer require nickpoulos/laravel-svelte-direct
```

### Configure Laravel Mix
webpack.mix.js
```javascript
const mix = require('laravel-mix');
require('laravel-svelte-direct-mix')
require('./vendor/nickpoulos/laravel-svelte-direct/js/mix');

mix.svelteDirect('resources/js/Components', 'public/js');

Expand All @@ -60,17 +59,9 @@ The options tag tells Svelte (and Svelte Direct), what the component's HTML tag
The comment tag tells Svelte to ignore when we don't have `customElement` set to true.


### Install Laravel Svelte Direct PHP

You can install the package via composer:

```bash
composer require nickpoulos/laravel-svelte-direct
```

### Configure Blade Template

In your applications's main Blade layout/component, add the `@sveltedirect`above your ending `</body>` tag.
In your applications's main Blade layout/component, add the `@stack('sveltedirect')'`above your ending `</body>` tag.

Feel free to add your Svelte component anywhere inside the Blade HTML. You will notice the tag we use in the HTML below matches the `<svelte:options>` tag attribute above.

Expand All @@ -97,7 +88,7 @@ example.blade.php
</script>

<!-- START Svelte Direct Component JavaScript -->
@sveltedirect
@stack('sveltedirect')
<!-- END Svelte Direct Component JavaScript -->

</body>
Expand Down
92 changes: 75 additions & 17 deletions src/SvelteDirectServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,67 +4,125 @@

use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class SvelteDirectServiceProvider extends ServiceProvider
{
/**
* @var array|null
*/
public ?array $manifest = [];
public array $tagsBeingUsed = [];

/**
* Main class entrypoint
*/
public function boot(): void
{
$this->loadManifestFile();
$this->loadBladePreCompiler();
$this->loadBladeDirective();
}

/**
* Provide the default path to the SvelteDirect manifest file
*
* @todo allow control via proper config file
*
* @internal
* @return string
*/
public function defaultManifestPath() : string
{
return App::bootstrapPath('cache/svelte-direct-components.php');
}

/**
* Loads the "tag name to JavaScript file" mapping
* aka manifest file
*
* @internal
* @param string|null $manifestFilePath
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function loadManifestFile(?string $manifestFilePath = null) : void
{
$files = new Filesystem();
$manifestPath = $manifestFilePath ?? $this->defaultManifestPath();
$this->manifest = file_exists($manifestPath) ? $files->getRequire($manifestPath):null;
}

/**
* Register our precompiler function within the Blade compiler engine
*
* @internal
*/
public function loadBladePreCompiler() : void
{
if (! $this->manifest) {
return;
}

$this->app['blade.compiler']->precompiler([$this, 'findTagsInBladeTemplate']);
$this->app['blade.compiler']->precompiler([$this, 'precompiler']);
}

public function loadBladeDirective() : void

/**
* Our precompiler function that finds any Svelte component tags
* and then appends the proper call to the @stack Blade directive
* to our existing Blade template code
*
* @param string $viewTemplateCode
* @return string
*/
public function precompiler(string $viewTemplateCode)
{
if (! $this->manifest) {
return;
}
$tagsToLoad = $this->findSvelteComponentTagsInBlade($viewTemplateCode);

Blade::directive('sveltedirect', [$this, 'generateDirectiveHtml']);
return $viewTemplateCode . $this->appendPushDirective($tagsToLoad);
}

/** @internal */
public function findTagsInBladeTemplate(string $view) : string

/**
* Given Blade template code, find any of our Svelte component tags
* that were used within the template
*
* @internal
* @param string $view
* @return array
*/
public function findSvelteComponentTagsInBlade(string $view) : array
{
$tagPattern = implode('|', array_keys($this->manifest));
$pattern = "/(?<=<)\s*{$tagPattern}/";
$pattern = "/(?<=<)\s*(?:{$tagPattern})(?=\s|>|\/)+/";
preg_match_all($pattern, $view, $matches);
$this->tagsBeingUsed = array_merge(array_unique($matches[0]), $this->tagsBeingUsed);

return $view;
return array_intersect(array_keys($this->manifest), array_unique($matches[0]));
}

/** @internal */
public function generateDirectiveHtml(string $expression) : string
/**
* Create the @push directive code for the given Svelte tags
*
* @internal
* @param array $tagsToLoad
* @return string
*/
public function appendPushDirective(array $tagsToLoad) : string
{
$tagsToLoad = array_intersect(array_keys($this->manifest), $this->tagsBeingUsed);
return "@push('sveltedirect')" . PHP_EOL .
$this->generateScriptHtml($tagsToLoad)
. PHP_EOL . "@endpush";
}


/**
* Generate the script tag HTML to load our component JavaScript file(s)
* for a given set of tags
*
* @internal
* @param array $tagsToLoad
* @return string
*/
public function generateScriptHtml(array $tagsToLoad) : string
{
return array_reduce($tagsToLoad, function ($previous, $current) {
return $previous . '<script src="{{ mix("' . $this->manifest[$current] . '") }}"></script>' . PHP_EOL;
}, '');
Expand Down
Loading

0 comments on commit 2f04e23

Please sign in to comment.