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

Support HTML Attributes on <script> Tag #122

Open
wants to merge 3 commits into
base: master
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
52 changes: 48 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ For Laravel users, there is a service provider you can make use of to automatica

When this provider is booted, you'll gain access to a helpful `JavaScript` facade, which you may use in your controllers.

## Usage

#### JavaScript::put(...)

The `JavaScript` facade has two public functions. The first/main one is `JavaScript::put(...)`, which transforms the given PHP data and passes it to the front-end view file.

For example:

```php
public function index()
{
Expand All @@ -61,17 +69,53 @@ console.log(age); // 29

This package, by default, binds your JavaScript variables to a "footer" view, which you will include. For example:

```
```html
<body>
<h1>My Page</h1>

@include ('footer') // <-- Variables prepended to this view
<!-- Variables prepended to this view -->
@include ('footer')
</body>
```

Naturally, you can change this default to a different view. See ["Defaults"](#defaults) below.

#### JavaScript::setHtmlAttributes($htmlAttributes)

The second public function provided by this facade is `JavaScript::setHtmlAttributes($htmlAttributes)`, which allows you to set the element attributes on the HTML `<script>` tag(s).
For example, if you need to add nonces to your script tags for your Content Security Policy, you can pass the attributes in as an array:

```php
public function index()
{
JavaScript::setHtmlAttributes([
'nonce' => csp_nonce(), // `csp_nonce()` is NOT provided by this package
]);

JavaScript::put([
'foo' => 'bar'
]);

return View::make('hello');
}
```

The above `JavaScript` calls would output something like this in the compiled view file:
```html
<body>
<script nonce="This_Is_A_Secure_Nonce">
JS.foo = "bar";
</script>
</body>
```

Naturally, you can change this default to a different view. See below.
> **NOTE**: This package does not provide any sort of Content Security Policy logic; the above is just an example of an additional HTML attribute you may need to add to a script tag.
>
> For more information on Content Security Policy, see [the Mozilla Developer docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP).
>
> If you do not already have CSP and are using Laravel, I would recommend package [spatie/laravel-csp](https://github.com/spatie/laravel-csp).

### Defaults
## Defaults

If using Laravel, there are only two configuration options that you'll need to worry about. First, publish the default configuration.

Expand Down
49 changes: 44 additions & 5 deletions src/LaravelViewBinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,54 @@ class LaravelViewBinder implements ViewBinder
*/
protected $views;

/**
* An array of HTML attributes to add to the <script> tag(s)
*
* @var array
*/
protected $htmlAttributes;

/**
* Create a new Laravel view binder instance.
*
* @param Dispatcher $event
* @param string|array $views
* @param array $attributes
*/
public function __construct(Dispatcher $event, $views, $htmlAttributes = [])
{
$this->event = $event;
$this->views = str_replace('/', '.', (array)$views);
$this->htmlAttributes = $htmlAttributes;
}

/**
* Set the array of HTML attributes
*
* @param array $htmlAttributes
*/
public function __construct(Dispatcher $event, $views)
public function setHtmlAttributes(array $htmlAttributes)
{
$this->event = $event;
$this->views = str_replace('/', '.', (array)$views);
$this->htmlAttributes = $htmlAttributes;
}

/**
* Get the list of HTML attributes, as an array or an HTML-ready string
*
* @param boolean $toString should we return the attributes as a string?
* @return array|string
*/
protected function getHtmlAttributes($toString = false)
{
if ($toString === false) {
return $this->htmlAttributes;
}

$out = "";
foreach ($this->htmlAttributes as $attribute => $value) {
$out .= " {$attribute}=\"{$value}\"";
}
return $out;
}

/**
Expand All @@ -39,9 +77,10 @@ public function __construct(Dispatcher $event, $views)
*/
public function bind($js)
{
$htmlAttributes = $this->getHtmlAttributes(true);
foreach ($this->views as $view) {
$this->event->listen("composing: {$view}", function () use ($js) {
echo "<script>{$js}</script>";
$this->event->listen("composing: {$view}", function () use ($htmlAttributes, $js) {
echo "<script{$htmlAttributes}>{$js}</script>";
});
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/Transformers/Transformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ public function put()
return $js;
}

/**
* Add HTML attributes to the <script> tag(s)
*
* @param array $attributes an associative array of attributes and values to add
*/
public function setHtmlAttributes(array $attributes)
{
$this->viewBinder->setHtmlAttributes($attributes);
}

/**
* Translate the array of PHP variables to a JavaScript syntax.
*
Expand Down
8 changes: 8 additions & 0 deletions src/ViewBinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,12 @@ interface ViewBinder
* @param string $js
*/
public function bind($js);


/**
* Set the array of HTML attributes for the <script> tag(s)
*
* @param array $htmlAttributes associative array of HTML element attributes
*/
public function setHtmlAttributes(array $htmlAttributes);
}