Skip to content

Commit

Permalink
feat: ✨ Add ability to prepend/append scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
TheDutchCoder committed May 9, 2021
1 parent 7846678 commit 4c03ccb
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 7 deletions.
49 changes: 46 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,70 @@ export default {
```

## Options
This plugin provides a couple of options that can be configured. Only the
`content` option is required.

### Position
```js
value: 'head' | 'body'
optional
default: 'head'
```
You can use the `position` option to add the script to either the head or the
body section of the index.html file. By default `'head'` will be assumed.
body section of the index.html file.

### Content
```js
value: string
required
```
The `content` option is the actual content that gets written to the file.
Normally it would be a stringified version of the script tags and their
contents.

The `sort` option can be used to determine the order the scripts get appended.
### Sort
```js
value: number
default: 0
```
The `sort` option can be used to determine the order the scripts get added.
This defaults to `0` and higher values appear later. Negative avlues are allowed
as well.

### Prepend
```js
value: boolean
default: false
```
The `prepend` option adds scripts directly after the `<head>` or `<body>` tag.
Scripts are appended by default.

```js
...ViteAddScripts([
{
sort: 3,
content: '<script>window.foo = {}</script>'
},
{
prepend: true,
sort: -2,
content: '<script>window.bar = {}</script>'
},
{
position: 'body',
content: '<script>window.baz = {}</script>'
}
},
{
position: 'body',
prepend: true,
content: '<script>window.this = {}</script>'
},
{
position: 'body',
prepend: true,
sort: -1,
content: '<script>window.that = {}</script>'
},
]),
```

Expand All @@ -72,9 +111,13 @@ Output:
<html>
<head>
<script>window.bar = {}</script>
<title>Title</title>
<script>window.foo = {}</script>
</head>
<body>
<script>window.that = {}</script>
<script>window.this = {}</script>
<p>content</p>
<script>window.baz = {}</script>
</body>
</html>
Expand Down
24 changes: 21 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { Plugin } from 'vite'
import { hasErrors, filterByPosition, sortScripts } from './utils'
import { hasErrors, filterByPosition, filterByPrepend, sortScripts } from './utils'

export const positions = ['head', 'body'] as const

export type Position = typeof positions[number];

export type Script = {
position?: Position;
prepend?: Boolean;
content: string;
sort?: number,
}
Expand All @@ -30,15 +31,32 @@ const VitePluginAddScripts = (scripts: Script[]): Plugin => {
headScripts = sortScripts(headScripts)
bodyScripts = sortScripts(bodyScripts)

// Sort by prepend/append.
const headPrependScripts = filterByPrepend(headScripts, true)
const headAppendScripts = filterByPrepend(headScripts, false)

const bodyPrependScripts = filterByPrepend(bodyScripts, true)
const bodyAppendScripts = filterByPrepend(bodyScripts, false)

// Append the scripts to the HTML.
html = html.replace(
/<head>/,
`<head>\n${headPrependScripts.map(script => script.content).join('\n')}`
)

html = html.replace(
/<\/head>/,
`${headScripts.map(script => script.content).join('\n')}\n</head>`
`${headAppendScripts.map(script => script.content).join('\n')}\n</head>`
)

html = html.replace(
/<body>/,
`<body>\n${bodyPrependScripts.map(script => script.content).join('\n')}`
)

html = html.replace(
/<\/body>/,
`${bodyScripts.map(script => script.content).join('\n')}\n</body>`
`${bodyAppendScripts.map(script => script.content).join('\n')}\n</body>`
)

return html
Expand Down
34 changes: 33 additions & 1 deletion src/utils/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { hasErrors, filterByPosition, sortScripts } from '../index'
import { hasErrors, filterByPosition, filterByPrepend, sortScripts } from '../index'
import type { Script } from '../../index'

describe('hasErrors', () => {
Expand Down Expand Up @@ -85,6 +85,38 @@ describe('filterByPosition', () => {
})
})

describe('filterByPrepend', () => {
it('filters scripts by their position', () => {
const items: Script[] = [
{ position: 'head', prepend: true, content: '1' },
{ position: 'head', content: '2' },
{ position: 'head', content: '3' },
{ position: 'head', prepend: true, content: '4' },
{ position: 'head', content: '5' },
]

const filteredPrependItems: Script[] = [
{ position: 'head', prepend: true, content: '1' },
{ position: 'head', prepend: true, content: '4' },
]

const filteredAppendItems: Script[] = [
{ position: 'head', prepend: false, content: '2' },
{ position: 'head', prepend: false, content: '3' },
{ position: 'head', prepend: false, content: '5' },
]

const headPrependResult = filterByPrepend(items, true)
const headAppendResult = filterByPrepend(items, false)

expect(headPrependResult.length).toBe(2)
expect(headPrependResult).toEqual(filteredPrependItems)

expect(headAppendResult.length).toBe(3)
expect(headAppendResult).toEqual(filteredAppendItems)
})
})

describe('sortScripts', () => {
it('sorts scripts by their sort key', () => {
const items: Script[] = [
Expand Down
10 changes: 10 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ export const filterByPosition = (scripts: Script[], position: Position): Script[
})
}

export const filterByPrepend = (scripts: Script[], prepend: Boolean): Script[] => {
return scripts.filter(script => {
if (!script.prepend) {
script.prepend = false
}

return script.prepend === prepend
})
}

export const sortScripts = (scripts: Script[]): Script[] => {
return scripts.sort((first, second) => {
if (!first.sort) {
Expand Down

0 comments on commit 4c03ccb

Please sign in to comment.