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

WIP - Add scripts support #24

Closed
Closed
Show file tree
Hide file tree
Changes from 15 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
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.history
47 changes: 47 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/** @type {import('eslint').Linter.BaseConfig} */
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's keep the PR focused on one thing, and make project setup changes a different PR.

const conf = {
reportUnusedDisableDirectives: true,
parser: '@typescript-eslint/parser',
extends: [
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/strict',
],
plugins: ['@typescript-eslint'],
// https://github.com/typescript-eslint/typescript-eslint/blob/6c3816b3831e6e683c1a7842196b34248803d69b/packages/eslint-plugin/docs/rules/explicit-function-return-type.md#configuring-in-a-mixed-jsts-codebase
rules: {
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_' },
],

// disabled globally, because it's not possible to satisfy these rules in js files (even with jsdoc comments)
// These are enabled specifically for TS in `overrides` below.
// TS may still complain about implicit any, etc in js code.
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-var-requires': 'off',

// Types created with `type` keyword can expand inline to become unreadable.
// Empty interfaces solve this problem - type hover boxes instead show the interface name,
// Instead of expanding full type inline.
'@typescript-eslint/no-empty-interface': 'off',
},
overrides: [
{
// enable the rule specifically for TypeScript files
files: ['*.ts', '*.tsx'],
rules: {
'@typescript-eslint/explicit-function-return-type': [
'error',
],
'@typescript-eslint/explicit-module-boundary-types': [
'error',
],
'@typescript-eslint/no-var-requires': ['error'],
},
},
],
}

module.exports = conf
1 change: 1 addition & 0 deletions .node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
16.20.1
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.history
23 changes: 23 additions & 0 deletions .prettierrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Prettier config to reduce merge conflicts: https://gist.github.com/devinrhode2/08c84e175c61b282b76f4766a94e4a01

/** @type {import('prettier').Options} */
const conf = {
endOfLine: 'lf',
singleQuote: true,
semi: false,

// avoid even more merge conflicts: https://prettier.io/blog/2020/03/21/2.0.0.html#change-default-value-for-trailingcomma-to-es5-6963httpsgithubcomprettierprettierpull6963-by-fiskerhttpsgithubcomfisker
trailingComma: 'all',
printWidth: 65,
// Less code per line means:
// - less likely to have conflict on any given line
// - easier to spot changes in git (e.g. getListThing->getListsThing)
// - Encourages modularity
// - jsx components with 20 indent levels will not look good
// - This encourages creating smaller components
// - Still can opt-out with `// prettier-ignore` comments above component
// - OR, create a `.prettierrc.js` file in code you edit the most
// - This exact number will always be somewhat arbitrary, it's not set in stone.
}

module.exports = conf
79 changes: 79 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
// Allow committing to any branch, until we need to establish a pr process
"git.branchProtectionPrompt": "alwaysPrompt",

"files.associations": {
".babelrc": "json5",
".git-blame-ignore-revs": "git-commit",
"*.template": "properties" // nginx.template
},

// Format markdown correctly:
"[markdown]": {
"editor.defaultFormatter": "DavidAnson.vscode-markdownlint"
},

// Nice to have for any repo:
// (use `typescript` version that's inside `node_modules`)
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,

// Better safe than sorry:
"git.useForcePushWithLease": true,

// Generic settings for our repo:
"editor.tabSize": 2,

// By default, format ALL file types with prettier onSave:
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",

// Enable eslint vscode extension:
"eslint.enable": true,
"eslint.format.enable": false, // assert default
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
"prettier.useEditorConfig": true,
"eslint.useESLintClass": true,
"eslint.probe": [],

// To improve performance a little bit, comment out rest of settings, and un-comment this line.
"editor.codeActionsOnSave": ["source.fixAll.eslint"]
// There is a small risk of hitting bugs like this: https://github.com/prettier/prettier-vscode/issues/1555

// Run eslint on save, then prettier afterwards
// Apologies if this affects any of your personal extensions - maybe we can add them into the repo?
// "editor.codeActionsOnSave": {},
// "[typescript]": {
// "editor.formatOnSave": false,
// "editor.codeActionsOnSave": [
// "source.fixAll.eslint",
// "source.formatDocument"
// ]
// },
// "[typescriptreact]": {
// "editor.formatOnSave": false,
// "editor.codeActionsOnSave": [
// "source.fixAll.eslint",
// "source.formatDocument"
// ]
// },
// "[javascript]": {
// "editor.formatOnSave": false,
// "editor.codeActionsOnSave": [
// "source.fixAll.eslint",
// "source.formatDocument"
// ]
// },
// "[javascriptreact]": {
// "editor.formatOnSave": false,
// "editor.codeActionsOnSave": [
// "source.fixAll.eslint",
// "source.formatDocument"
// ]
// }
}
20 changes: 12 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,39 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Added

* Added `delegates-focus` attribute: https://github.com/justinfagnani/html-include-element/pull/13
- Added `delegates-focus` attribute: https://github.com/justinfagnani/html-include-element/pull/13

### Fixed

* Fixed a bug with the `load` event: https://github.com/justinfagnani/html-include-element/pull/12

- Fixed a bug with the `load` event: https://github.com/justinfagnani/html-include-element/pull/12

## [0.2.0] - 2020-02-21

### Added
* Defer firing the `load` event until all `<link>` elements in the shadow root are finished loading.

- Defer firing the `load` event until all `<link>` elements in the shadow root are finished loading.

### Fixed
* Preserve light DOM content when including into shadow DOM

- Preserve light DOM content when including into shadow DOM

## [0.1.3] - 2019-05-01

### Fixed

* Add `<slot>` to project content when using `no-shadow`
- Add `<slot>` to project content when using `no-shadow`

## [0.1.2] - 2019-04-16

### Fixed
* Handle possible race condition when changing the `src` attribute.

- Handle possible race condition when changing the `src` attribute.

## [0.1.1] - 2019-04-16

### Fixed
* Add repository to package.json

- Add repository to package.json

## [0.1.0] - 2019-04-16

Expand Down
29 changes: 18 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ Easily include external HTML into your pages.

`<html-include>` works with any framework, or no framework at all.

By default `<html-include>` renders the HTML in a shadow root, so it's isolated from the rest of the page. This can be configured with the `no-shadow` attribute.
By default `<html-include>` renders the HTML in a shadow root, so it's isolated from the rest of the page. ~This can be configured with the `no-shadow` attribute.~ Devin's with-scripts fork has (at least temporarily) suspended support for `no-shadow`, i.e. setting the `no-shadow` attribute is unsupported and will probably not work, or at least not work correctly in all cases.

## Installation
## Installation

Install from npm:

Expand All @@ -32,7 +32,10 @@ You can load it into a page with a `<script>` tag:

```html
<head>
<script type="module" src='https://unpkg.com/html-include-element'></script>
<script
type="module"
src="https://unpkg.com/html-include-element"
></script>
</head>
<body>
<html-include src="./my-local-file.html"></html-include>
Expand All @@ -42,7 +45,7 @@ You can load it into a page with a `<script>` tag:
Or import into a JavaScript module:

```js
import {HTMLIncludeElement} from 'html-include-element';
import { HTMLIncludeElement } from 'html-include-element'
```

`<html-include>` fires a `load` even when the included file has been loaded. When including into shadow DOM (the default behavior) the `load` event is fired after any `<link>` elements in the included file have loaded as well.
Expand Down Expand Up @@ -71,7 +74,7 @@ The URL to fetch an HTML document from.

### `mode`

The fetch mode to use: "cors", "no-cors", or "same-origin". See the fetch() documents for more information.
The fetch mode to use: "cors", "no-cors", or "same-origin". See the fetch() documentation for more information.

### `no-shadow`

Expand All @@ -87,7 +90,7 @@ Web components are supported by Chrome, Safari, Firefox, Opera and other Chromiu

Other browsers, like current versions Edge and older but recent versions of Chrome, Safari, and Firefox, will require the web components polyfills.

IE11 *may* work with the polyfills if this library is compiled, but that would be accidental: IE is explicitly not supported.
IE11 _may_ work with the polyfills if this library is compiled, but that would be accidental: IE is explicitly not supported.

The web component polyfills can be loaded from unpkg.com:

Expand All @@ -109,15 +112,15 @@ npm i @webcomponents/webcomponentsjs

This is a personal side-project and published basically "as-is". I will try to get CI running, add more tests, and improve the documentation as time permits. PRs welcome, but if I'm not responsive, please feel free to fork.

And no, I will not publish an ES5 version 🤨. Applications can compile to the language level their target browsers support. Bundlers can and should be configured to compile packages in `node_modules` as necessary.
And no, I will not publish an ES5 version 🤨. Applications can compile to the language level their target browsers support. Bundlers can and should be configured to compile packages in `node_modules` as necessary.

## Alternate Approaches

I made this project after seeing this blog post on using iframes to implement HTML-include behavior: https://www.filamentgroup.com/lab/html-includes/
I made this project after seeing this blog post on using iframes to implement HTML-include behavior: <https://www.filamentgroup.com/lab/html-includes/>

That approach uses an iframe to load the external HTML document, then inline script to move the nodes into the main document. I believe the web component approach is far better for a few reasons:

### CSP Compliant
### CSP Compliant

`onload` attributes are blocked by CSP most policies.

Expand All @@ -127,9 +130,11 @@ By using `fetch()` we can make a CORS request for the content. A cross-origin if

For the web components, more options from `fetch()` can be exposed as well, such as `method`, `body`, `integrety`, and `cache`.

### Scripts don't execute
### ~Scripts don't execute~

iframes will execute scripts. Cross-origin documents won't be moved into the main page, so their scripts will run to completion. I'm not exactly sure what will happen with same-origin script when they are moved into the main document. It may depend on the presence of other scripts or external resources. Either way, it's a feature that `<html-include>` will not run scripts due to using `innerHTML`.
~iframes will execute scripts. Cross-origin documents won't be moved into the main page, so their scripts will run to completion. I'm not exactly sure what will happen with same-origin script when they are moved into the main document. It may depend on the presence of other scripts or external resources. Either way, it's a feature that `<html-include>` will not run scripts due to using `innerHTML`.~

This fork includes a work-around, instead of setting `innerHTML`, it will include parse using dom methods, select `<script>` tags, store the script attributes (src/etc) in a new data structure, and then append those scripts in the same order they appeared in the original html document.

### Consistent styling

Expand All @@ -152,13 +157,15 @@ Having the implementation of the include be re-written for every instance will m
Since the included HTML is rendered in a shadow root, it can contain `<slot>` elements, allowing the included content to project children from the `<html-include>` into itself. This may be a fringe case, but imaging a CMS system where the content can control where certain host-provided blocks go. I'm very curious to see how this might be used.

Main page:

```html
<html-include>
<div slot="suggested-articles">...</div>
</html-include>
```

Content:

```html
<article>
<header>...</header>
Expand Down
Loading