Skip to content

Commit

Permalink
Add the crossorigin property to the external
Browse files Browse the repository at this point in the history
  • Loading branch information
mentaljam committed Dec 9, 2019
1 parent 658ecba commit 584738c
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 35 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ meta: {

```js
{
crossorigin?: 'anonymous' | 'use-credentials'
file: string
type?: undefined | 'css' | 'js'
pos: 'before' | 'after'
Expand All @@ -132,7 +133,8 @@ meta: {
An array of additional files that will be injected to the output HTML document. Only CSS and JS files
are accepted. The optional `type` property points which type of file is injected. If type is `undefined`
then it is detected based on the file extension. The `pos` property points when the file is inserted:
before processing the budnled files or after.
before processing the bundled files or after. The optional `crossorigin` property points whether to place
the CORS attribute to the generated tag.

##### Example

Expand Down
1 change: 1 addition & 0 deletions example/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default {
externals: [{
file: 'https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css',
pos: 'before',
crossorigin: 'use-credentials',
}],
preload: ['lib'],
minify: {
Expand Down
97 changes: 63 additions & 34 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,23 @@ const enum InjectType {
js = 'js',
}

const enum ExternalPosition {
enum ExternalPosition {
before = 'before',
after = 'after',
}

enum Crossorigin {
anonymous = 'anonymous',
usecredentials = 'use-credentials',
}

interface IExternal {
crossorigin?: Crossorigin
file: string
type?: InjectType
pos: ExternalPosition
}

type ExtrenalsProcessor = (pos: ExternalPosition) => void

interface IPluginOptions {
template: string
file?: string
Expand Down Expand Up @@ -111,6 +115,55 @@ const formatSupportsModules = (f?: ModuleFormat) => (
|| f === 'module'
)

const checkEnum = <T extends {}>(enumobj: T, val?: string) => (
!val || Object.values(enumobj).includes(val)
)

const injectCSSandJSFactory = (
head: HTMLElement,
body: HTMLElement,
modules?: boolean,
) => {
const typeModule = modules ? 'type="module" ' : ''

return (
fileName: string,
type: InjectType | string,
pos?: Inject,
crossorigin?: Crossorigin,
) => {
const cors = crossorigin ? `crossorigin="${crossorigin}" ` : ''
if (type === InjectType.css) {
const parent = pos === Inject.body ? body : head
addNewLine(parent)
parent.appendChild(new HTMLElement('link', {}, `rel="stylesheet" ${cors}href="/${fileName}"`))
} else {
const parent = pos === Inject.head ? head : body
addNewLine(parent)
parent.appendChild(new HTMLElement('script', {}, `${typeModule}${cors}src="/${fileName}"`))
}
}
}

type ExtrenalsProcessor = (pos: ExternalPosition) => void

const extrenalsProcessorFactory = (
injectCSSandJS: ReturnType<typeof injectCSSandJSFactory>,
externals?: IExternal[],
): ExtrenalsProcessor => {
if (!externals) {
// tslint:disable-next-line: no-empty
return (_pos) => {}
}
return (processPos) => {
for (const {pos, file, type, crossorigin} of externals) {
if (pos === processPos) {
injectCSSandJS(file, type || path.extname(file).slice(1), undefined, crossorigin)
}
}
}
}

export default ({
template,
file,
Expand Down Expand Up @@ -150,10 +203,13 @@ export default ({
}

if (externals) {
for (const {pos} of externals) {
if (pos !== ExternalPosition.before && pos !== ExternalPosition.after) {
for (const {pos, crossorigin} of externals) {
if (!checkEnum(ExternalPosition, pos)) {
this.error('Invalid position for the extrenal: ' + pos)
}
if (!checkEnum(Crossorigin, crossorigin)) {
this.error('Invalid crossorigin argument for the extrenal: ' + crossorigin)
}
}
}

Expand Down Expand Up @@ -248,35 +304,8 @@ consider to use the esm format or switch off the option`)
}
}

const injectCSSandJS = (fileName: string, type: string, pos: Inject | undefined = undefined) => {
const cssParent = pos !== Inject.body ? head : body
const jsParent = pos !== Inject.head ? body : head
switch (type) {
case InjectType.css:
addNewLine(cssParent)
cssParent.appendChild(new HTMLElement('link', {}, `rel="stylesheet" href="/${fileName}"`))
break
case InjectType.js:
addNewLine(jsParent)
const typeModule = modules ? 'type="module" ' : ''
jsParent.appendChild(new HTMLElement('script', {}, `${typeModule}src="/${fileName}"`))
break
default:
break
}
}

const processExternals: ExtrenalsProcessor = externals ?
(pos) => {
for (const external of externals) {
if (external.pos === pos) {
injectCSSandJS(external.file, external.type || path.extname(external.file).slice(1))
}
}
}
:
// tslint:disable-next-line: no-empty
(_pos) => {}
const injectCSSandJS = injectCSSandJSFactory(head, body, modules)
const processExternals = extrenalsProcessorFactory(injectCSSandJS, externals)

// Inject externals before
processExternals(ExternalPosition.before)
Expand Down

0 comments on commit 584738c

Please sign in to comment.