Full Code of gustafnk/h-include for AI

main 0fd97f999afa cached
79 files
91.3 KB
26.3k tokens
11 symbols
1 requests
Download .txt
Repository: gustafnk/h-include
Branch: main
Commit: 0fd97f999afa
Files: 79
Total size: 91.3 KB

Directory structure:
gitextract_u4czxxj4/

├── .github/
│   └── workflows/
│       └── main.yml
├── .gitignore
├── .jshintrc
├── .npmignore
├── EXTENDING.md
├── FAQ.md
├── LICENSE.md
├── README.md
├── __tests__/
│   ├── README.md
│   ├── browser-test.js
│   ├── browsers-local.json
│   └── browsers-remote.json
├── h-include.js
├── lib/
│   ├── h-include-extensions.js
│   └── h-include.js
├── package.json
├── release-with-deprecation-warning.js
└── static/
    ├── alt/
    │   ├── alt.html
    │   ├── fragment.html
    │   ├── fragment2.html
    │   ├── fragment3.html
    │   ├── fragment4.html
    │   ├── no-alt.html
    │   ├── when-fail-no-when-false-src-alt-error.html
    │   ├── when-fail-no-when-false-src-alt-pass.html
    │   ├── when-fail-when-false-src-fail-alt-error.html
    │   ├── when-fail-when-false-src-fail-alt-pass.html
    │   ├── when-pass-no-when-false-src-alt-error.html
    │   ├── when-pass-no-when-false-src-alt-pass.html
    │   ├── when-pass-when-false-src-fail-alt-error.html
    │   └── when-pass-when-false-src-fail-alt-pass.html
    ├── basic/
    │   ├── fragment-2.html
    │   ├── fragment.html
    │   └── index.html
    ├── basic-async/
    │   ├── fragment-2.html
    │   ├── fragment.html
    │   └── index.html
    ├── expect.js
    ├── fragment-extraction/
    │   ├── full-page.html
    │   └── index.html
    ├── index.html
    ├── lazy-extension/
    │   ├── fragment-3.html
    │   ├── fragment.html
    │   └── index.html
    ├── media/
    │   ├── index.html
    │   ├── large.html
    │   └── small.html
    ├── navigate-extension/
    │   ├── 1.html
    │   ├── 2.html
    │   ├── 3.html
    │   ├── extract-fragment/
    │   │   ├── 1.html
    │   │   ├── 2.html
    │   │   ├── 3.html
    │   │   └── index.html
    │   ├── index.html
    │   └── nested/
    │       ├── 1.html
    │       ├── 2.html
    │       ├── 3.html
    │       ├── index.html
    │       └── inner.html
    ├── none/
    │   └── index.html
    ├── recursion-not-allowed/
    │   ├── index.html
    │   └── recursive-fragment.html
    ├── style.css
    ├── visual-tests/
    │   ├── domparser/
    │   │   ├── body.html
    │   │   ├── domparser.html
    │   │   ├── main.html
    │   │   └── partial.html
    │   └── import-extension/
    │       ├── index.html
    │       ├── resource-fragment.html
    │       ├── script-1.js
    │       ├── script-2.js
    │       ├── styles-1.css
    │       └── styles-2.css
    └── when/
        ├── fragment.html
        ├── fragment2.html
        ├── when-fail-if-when-false-src.html
        ├── when-fail.html
        └── when-pass-use-src.html

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/main.yml
================================================
name: browser test
on: [push, workflow_dispatch]
jobs:
    test:
        runs-on: ubuntu-latest
        name: Action Test
        steps:
            # ...
            - uses: saucelabs/sauce-connect-action@v2.0.0
              with:
                  username: ${{ secrets.SAUCE_USERNAME }}
                  accessKey: ${{ secrets.SAUCE_ACCESS_KEY }}
                  tunnelIdentifier: github-action-tunnel
                  scVersion: 4.6.4
            # ...
            - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
            - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
            - name: Check out repository code
              uses: actions/checkout@v2
            - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
            - run: echo "🍏 This job's status is ${{ job.status }}."
            - run: npm install
            - env:
                SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
                SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
              run: PORT=8080 npm run remote-tests


================================================
FILE: .gitignore
================================================
static/error.png
npm-debug.log
node_modules/
h-include

.DS_Store


================================================
FILE: .jshintrc
================================================
{
  "expr": true
}

================================================
FILE: .npmignore
================================================
__tests__
static
.jshintrc
.travis.yml
EXTENDING.md
FAQ.md
favicon.ico
release-with-deprecation-warning.js
.github


================================================
FILE: EXTENDING.md
================================================
# Extending h-include

Extending h-include is quite simple. Follow the pattern below and then look at the method table at the bottom of this page.

You might want to read the source code of lib/h-include.js and lib/h-include-extensions.js to know how this are connected and to get inspired.

```
(function() {
  var proto = Object.create(HInclude.HIncludeElement.prototype);

  proto.connectedCallback = function(){ ... };

  var MyOwnIncludeElement = function() {
    return Reflect.construct(HTMLElement, arguments, MyOwnIncludeElement);
  };
  MyOwnIncludeElement.prototype = proto;

  customElements.define('my-own-include', MyOwnIncludeElement);
  return MyOwnIncludeElement;
})();
```

If needed, you can also call the "super method" like this:
```
window.HInclude.HIncludeElement.prototype.methodThatWasOverridden.apply(this, arguments);
```

(Note: In h-include 3.0, `window.HIncludeElement` was moved to `window.HInclude.HIncludeElement`)

## Overridable methods

| Function | Arguments | Default behavior | Returns                                                     |
|-----------------|------------------------------|------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
| `createContainer` | `request` | Creates a DOM container from the request | DOM element |
| `extractFragment` | `container`, `fragment`, `request` | Queries the container with a fragment selector. The default fragment selector is 'body'. | DOM Element |
| `replaceContent`  | `fragmentElement` | Replaces the innerHTML of the element with the innerHTML of the fragmentElement | `void` |
| `onEnd`  | `request` | Add status information to the `@class` attribute of the h-include element | `void` |



================================================
FILE: FAQ.md
================================================
# Frequently asked questions

## Can I include fragments from other hostnames?

Yes, if the remote origin supports CORS for your hostname (like all AJAX).

## Why can't I used self-closing tags?

Because it seems like [W3C will never support Custom Elements with self-closing tags](https://github.com/w3c/webcomponents/issues/624).


================================================
FILE: LICENSE.md
================================================
MIT License

Copyright (c) 2016-2019 Gustaf Nilsson Kotte <gustaf.nk@gmail.com>
Copyright (c) 2005-2012 Mark Nottingham <mnot@mnot.net>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# h-include.js

Declarative client-side transclusion, using [Custom Elements V1](https://developers.google.com/web/fundamentals/web-components/customelements). Perfect for [Microfrontend architectures](https://micro-frontends.org/), in combination with server-side transclusion technologies like [Edge-Side Includes](https://en.wikipedia.org/wiki/Edge_Side_Includes).

Based on [hinclude.js](https://github.com/mnot/hinclude) by [@mnot](https://github.com/mnot/).

*Breaking changes in version 4.0.0*:

Rename `alt` attribute to `when-false-src` to support future feature for error handling.

*Breaking changes in version 3.0.0*:

- Because h-include is now using Custom Elements V1, we recommend that you update your polyfill (i.e. [document-register-element](https://github.com/WebReflection/document-register-element)) to the latest version.
- If you have created your own custom elements that inherit from h-include, they too need to be based on Custom Elements V1. See [EXTENDING.md](EXTENDING.md) for an example how to extend h-include.
- The `navigate` attribute is broken out into the separate element `<h-include-navigate>`, located in `lib/h-include-extensions.js`.
- Changes to @src attribute don't automatically refresh an h-include element anymore

## Usage

Include an HTML resource like this:

```
<h-include src="/url/to/fragment.html"></h-include>
```

Each `<h-include>` element will create an AJAX request to the URL and replace the `innerHTML` of the element with the response of the request.

See [the demo page](http://gustafnk.github.com/h-include/) for live examples.

## Installation

Install using npm:

```shell
$ npm install h-include
```

## Rendering Mode

By default, each include is fetched in the background and the page is updated only when they all are available.

This is bounded by a timeout, by default 2500 ms. After the timeout,
h-include will show what it has and keep on listening for the remaining responses.

However, it's also possible to have responses from `<h-include>` elements become visible as they become available, by providing configuration:

```
HIncludeConfig = { mode: 'async' };
```

While this shows the included content quicker, it may be less visually smooth.

## Custom Elements polyfill

You need to use a polyfill for enabling [W3C Custom Elements](http://w3c.github.io/webcomponents/spec/custom/) for browsers not supporting Custom Elements V1.

We recommend using [document-register-element](https://github.com/WebReflection/document-register-element) (5KB minified and gzipped) as the polyfill for [W3C Custom Elements](http://w3c.github.io/webcomponents/spec/custom/).

Example:

```
<head>
  <script>this.customElements||document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');</script>
  <script type="text/javascript" src="/path/to/h-include.js"></script>
</head>
<body>
  ...
  <h-include src=">
  ...
</body>
```

## Extensions

Additional extensions are located in [`lib/h-include-extensions.js`](https://github.com/gustafnk/h-include/blob/master/lib/h-include-extensions.js) and have `lib/h-include.js` as a dependency:

```
<script type="text/javascript" src="/lib/h-include.js"></script>
<script type="text/javascript" src="/lib/h-include-extensions.js"></script>
```

All extensions inherit h-include's base behavior, when applicable.

To create your own elements that inherit from `<h-include>`, see [EXTENDING.md](EXTENDING.md).

Example usage, in summary:

| Resource fragments  | Content fragments  | Example |
|---|---|---|
| ESI | ESI | Short static pages |
| ESI | h-include  | Dynamic web app with static content fragments (i.e. search) |
| ESI | ESI + h‑include‑lazy | Pages with *homogeneous* lists, lazy loaded on scroll below the fold |
| ESI + h‑import‑lazy | ESI + h‑include‑lazy | Pages with *heterogeneous* content, lazy loaded on scroll below the fold together with resource fragments |
| h‑import | h‑include (etc) | Sites without access to ESI |

### h-include-lazy

Only includes the HTML resource if the element is about to enter the viewport, by default 400 pixels margin, using the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) (which needs to be polyfilled).

After page load, elements in the DOM need to registered to the Intersection Observer:

```
<script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
<script type="text/javascript" src="/lib/h-include.js"></script>
<script type="text/javascript" src="/lib/h-include-extensions.js"></script>
<script>
window.addEventListener('load', function() {
  HInclude.initLazyLoad();
});
</script>
```

Example:

```
<h-include-lazy src="fragment.html"></h-include-lazy>

...


<h-include-lazy src="lazy-loaded-fragment.html"></h-include-lazy>
```

Example repo using plain h-include (without lazy) and the Intersection Observer API to pull in content on ‘in-view’ scroll interaction can be found [here](https://github.com/nicolasdelfino/iobserver-h-include).

### h-import

Request an HTML resource and include all found script and stylesheet references.

Example:

```
<h-import src="resource-fragment.html"></h-import>
```

If possible, use [Edge-Side Includes](https://en.wikipedia.org/wiki/Edge_Side_Includes) (or similar) to import statically loaded resource fragments, due to performance reasons.

To load resources, h-import and h-import-lazy call `HInclude.loadResources` with an array of urls to resources. By default, this method delegates the resource loadin to [loadjs](https://github.com/muicss/loadjs), which needs to be on the `window` object. However, `HInclude.loadResources` can be replaced with a loader of your choice.

### h-import-lazy

When lazy loading fragments, it might be the case that additional style and script resources need to be loaded as well. For example, think of a lazy loaded footer with rather specific styling. For these scenarios, use h-import-lazy.

After page load, elements in the DOM need to registered to the Intersection Observer:

```
<script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
<script type="text/javascript" src="/lib/h-include.js"></script>
<script type="text/javascript" src="/lib/h-include-extensions.js"></script>
<script>
window.addEventListener('load', function() {
  HInclude.initLazyLoad();
});
</script>
```

Example:

```
<h-include-lazy src="fragment.html"></h-include-lazy>

...


<h-import-lazy src="lazy-loaded-resource-fragment.html"></h-import-lazy>
```

## h-include-navigate

Use `<h-include-navigate>` to let link navigation events be captured by the element itself, which changes the `src` attribute and triggers a refresh.

Use `target="_top"` to let link inside `h-include` behave as a normal link.


#### Helper function: HInclude.initLazyLoad

By default, the selector for `HInclude.initLazyLoad` is `'h-include-lazy, h-import-lazy'` and the Intersection Observer `rootMargin` and `threshold` default values are `400px 0px` and `0.01` respectively. These can be overridden:

```
HInclude.initLazyLoad('css style selector', {rootMargin: '200px 0', threshold: 0.2});
```

#### Helper function: HInclude.loadResources

Load an array of script and stylesheet resources (to be overridden).

## Advanced usage

### Conditional inclusion using when

When offers a way of using a predicate for inclusion. It also features an optional `when-false-src` attribute that functions as the source of inclusion given that the predicate fails.

```
<h-include src="logged-in.html" when="org.project.predicateFunction" when-false-src="log-in.html"></h-include>
```

The method specified in the when attribute may be namespaced and needs to return true for the inclusion of the url specified in the src attribute to occur.

### Request errors and alternative inclusion using alt

The alt attribute functions as an alternative source of inclusion should the url result in a request error.

```
<h-include src="unavailable.html" alt="alternative.html"></h-include>
```

### Refresh method

Refresh an element by using the `refresh()` method:

```js
const element = document.getElementsByTagName('h-include')[0];
element.refresh();
```

### Media queries

Use media queries to have different fragments for different devices:

```
<h-include media="screen and (max-width: 600px)" src="small.html"></h-include>
<h-include media="screen and (min-width: 601px)" src="large.html"></h-include>
```

`<h-include>` will not listen to changes to screen orientation or size.

### Fragment extraction

Include an HTML resource and extract a fragment of the response by using a selector:

```
<h-include src="..." fragment=".container"></h-include>
```

### XMLHttpRequest.withCredentials

Enable [XMLHttpRequest.withCredentials](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials):
```
<h-include src="..." with-credentials></h-include>
```

## Configuration

Set buffered include timeout (default is `2500` ms):

```js
HIncludeConfig = { timeout: 10000 };
```

Set include mode to `async` (default is `buffered`):

```js
HIncludeConfig = { mode: 'async' };
```

Throw if caught in an infinite include loop (default is `false`):

```js
HIncludeConfig = { checkRecursion: true };
```

If `checkRecursion` is `true`, h-include will traverse the DOM upwards to find another h-include element with the same src attribute, until the root node. This operation takes a few CPU cycles per h-include, which is why it's not enable by default.


## Error Handling

If fetching the included URL results in a 404 Not Found status code, the class of the include element will be changed to include_404. Likewise, a 500 Server Error status code will result in the include element’s class being changed to include_500.

## Browser support

All modern browsers and IE down to IE10 are supported. If you find something quirky, please file an issue.

## HTTP/2 improves XHR performance

Browsers with HTTP/2 are [using HTTP/2 for xhr requests as well](http://stackoverflow.com/questions/32592258/do-current-xhr-implementations-take-advantage-of-http-2). So, if both the server and the current browser supports HTTP/2, all requests made with h-include will go through the same TCP connection, given that they have the same origin.

## Bundler 

### Parcel

With this plugin, Parcel searches and optimizes all h-include tags
[https://github.com/joserochadocarmo/parcel-plugin-h-include](https://github.com/joserochadocarmo/parcel-plugin-h-include)


## FAQ

Please see the [FAQ](FAQ.md) for some frequently asked questions.



================================================
FILE: __tests__/README.md
================================================

Tests
=====

Requirements
------------

 * node (version 7.6 or higher)
 * npm

After this we can set up the project
 
  > npm install

This will install the selenium-webdriver and the other required nodejs modules.


Running local tests from the command-line
-----------------------------------

Install one or more browsers supported by [selenium-webdriver](http://seleniumhq.github.io/selenium/docs/api/javascript/index.html).

To run all the tests for the browsers in `browsers-local.json` on the local machine

  > npm run local-tests


Running Sauce Labs tests from the command-line
-----------------------------------

Install [Sauce Connect Proxy](https://wiki.saucelabs.com/display/DOCS/Sauce+Connect+Proxy). Unzip, cd into the folder and run

  > bin/sc -u [sauce username] -k [sauce access ke] -i tunnel1

Open a new terminal tab...

  > SAUCE_TUNNEL_ID=tunnel1 SAUCE_USERNAME=[sauce username] SAUCE_ACCESS_KEY=[sauce access key] npm run remote-tests


CI Testing
----------

TODO: Github Actions integration (work started).

Today, tests need to be run at a local dev machine.

Testing is done in the browser / OS environments defined in "__tests__/browsers.json".


Manual Testing in IE11
--------------

IE11 is hard to reliably automate through Selenium. Therefore, use the links in the `static/index.html` page and (for each link) wait for the alerts to be shown.



================================================
FILE: __tests__/browser-test.js
================================================
const path = require('path');
const fs = require('fs');

const expect = require('expect');
const { Builder, By, Key, until } = require('selenium-webdriver');

const SauceLabs = require('saucelabs').default

const username = process.env.SAUCE_USERNAME,
    accessKey = process.env.SAUCE_ACCESS_KEY,
    saucelabs = new SauceLabs({
      username: username,
      password: accessKey
    });

const caps = {};
let browsers;

const timeout = 6000;
const smallTimeout = 1000;
const longTimeout = 180000;
const log = true;

if (process.env.IS_LOCAL === 'true') {
  browsers = JSON.parse(fs.readFileSync(path.resolve(__dirname, 'browsers-local.json'), 'utf8'));
} else {
  browsers = JSON.parse(fs.readFileSync(path.resolve(__dirname, 'browsers-remote.json'), 'utf8'));

  // Setup Travis and SauceLabs
  var tunnelId, buildId;
  if (process.env.TRAVIS === 'true') {
    tunnelId = process.env.TRAVIS_JOB_NUMBER;
    buildId = process.env.TRAVIS_BUILD_NUMBER;
  }
  else if (process.env.SAUCE_TUNNEL_ID) {
    tunnelId = process.env.SAUCE_TUNNEL_ID;
    buildId = 0;

    Object.assign(caps, {
      host: '127.0.0.1',
      port: 4445,
    });
  }

  Object.assign(caps, {
    'tunnel-identifier': tunnelId,
    build: buildId,
    username: username,
    accessKey: accessKey,
    screenResolution: "1600x1200"
  });
}

browsers.forEach(browser => {
  const browserString = JSON.stringify(browser);

  describe(`h-include - ${browserString}`, () => {
    let driver;

    beforeEach(() => {
      if (process.env.IS_LOCAL === 'true') {
        driver = new Builder().forBrowser(browser.browserName).build();
      } else {
        Object.assign(caps, browser);

        server = 'http://' + username + ':' + accessKey +
                  '@ondemand.saucelabs.com:80/wd/hub';

        driver = new Builder().
          withCapabilities(caps).
          usingServer(server).
          build();

        driver.getSession().then(function (sessionid){
          driver.sessionID = sessionid.id_;
          console.log(`SauceOnDemandSessionID=${driver.sessionID} job-name=${browserString}`);
        });
      }
    });

    it('includes basic case', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/basic/');

      // Debugging
      // const html = await driver.findElement(By.tagName('html')).getAttribute('innerHTML');
      // console.log(html);

      const aSelector = By.id('included-1');
      const bSelector = By.id('included-2');

      await driver.wait(until.elementLocated(aSelector), timeout);
      const a = await driver.findElement(By.id('included-1'));

      await driver.wait(until.elementLocated(By.id('included-2')), timeout);
      const b = await driver.findElement(bSelector);

      const aText = await a.getText();
      const bText = await b.getText();

      expect(aText).toBe('this text is included');
      expect(bText).toBe('this text overwrote what was just there');
    });

    it('includes basic async case', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/basic-async/');
      const aSelector = By.id('included-1');
      const bSelector = By.id('included-2');

      await driver.wait(until.elementLocated(aSelector), timeout);
      const a = await driver.findElement(aSelector);

      await driver.wait(until.elementLocated(bSelector), timeout);
      const b = await driver.findElement(bSelector);

      const aText = await a.getText();
      const bText = await b.getText();

      expect(aText).toBe('this text is included');
      expect(bText).toBe('this text overwrote what was just there');
    });

    it('includes lazy', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/lazy-extension/');
      const aSelector = By.id('included-3');

      await driver.wait(until.elementLocated(aSelector), longTimeout);
      const a = await driver.findElement(aSelector);

      const aText = await a.getText();

      expect(aText).toBe('this text is included 3');
    });

    it('includes fragment with extraction', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/fragment-extraction/');
      const aSelector = By.id('a');

      await driver.wait(until.elementLocated(aSelector), timeout);
      const a = await driver.findElement(aSelector);

      const aText = await a.getText();

      expect(aText).toBe('Paragraph in fragment');
    });

    it('does not modify the page if no includes', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/none/');
      const aSelector = By.id('a');

      await driver.wait(until.elementLocated(aSelector), timeout);
      const a = await driver.findElement(aSelector);

      const aText = await a.getText();

      expect(aText).toBe('1st para');
    });

    it('does not allow recursion', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/recursion-not-allowed/');

      const aSelector = By.id('a');

      await driver.wait(until.elementLocated(aSelector), timeout);
      const a = await driver.findElement(aSelector);

      const aText = await a.getText();

      expect(aText).toBe('1');
    });

    it('navigates', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/navigate-extension/');

      await driver.wait(until.elementLocated(By.id('a')), longTimeout);
      await driver.findElement(By.css('#a .link')).click();

      await driver.wait(until.elementLocated(By.id('b')), longTimeout);
      await driver.findElement(By.css('#b .link')).click();

      const cSelector = By.id('c');
      await driver.wait(until.elementLocated(cSelector), longTimeout);

      const c = await driver.findElement(cSelector);

      const cText = await c.getText();

      expect(cText).toBe('This is the last box. Goodbye.');
    });

    // When
    it('does perform inclusion of src when predicate function succeeds', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/when/when-pass-use-src.html');

      const a = await driver.findElement(By.id('when-included')).getText();

      expect(a.trim()).toBe('when - this text is included');
    });

    it('does not perform inclusion of src when predicate function fails', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/when/when-fail.html');

      try {
        await driver.findElement(By.id('when-included'), smallTimeout)
      } catch (error) {
        expect(error.name).toBe('NoSuchElementError');
      }
    });

    it('does not perform inclusion of when-false-src when predicate function fails', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/when/when-fail.html');

      try {
        await driver.findElement(By.id('when-false-src-included'), smallTimeout)
      } catch (error) {
        expect(error.name).toBe('NoSuchElementError');
      }
    });

    it('does perform inclusion of when-false-src when predicate function fails', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/when/when-fail-if-when-false-src.html');

      try {
        await driver.findElement(By.id('when-included'), smallTimeout)
      } catch (error) {
        expect(error.name).toBe('NoSuchElementError');

        const a = await driver.findElement(By.id('when-false-src-included')).getText();

        expect(a.trim()).toBe('when-false-src - this text is included');
      }
    });

    // Alt
    it('uses alt attribute when forcing a 404', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/alt/alt.html');

      try {
        await driver.wait(until.elementLocated(By.id('default-included')), smallTimeout);
      } catch (error) {
        expect(error.name).toBe('TimeoutError');

        const cSelector = By.id('alt-included');
        await driver.wait(until.elementLocated(cSelector), timeout);

        const c = await driver.findElement(cSelector);
        const cText = await c.getText();

        const dSelector = By.id('alt-2-included');
        await driver.wait(until.elementLocated(dSelector), timeout);

        const d = await driver.findElement(dSelector);
        const dText = await d.getText();

        expect(cText).toBe('alt - this text is included');
        expect(dText).toBe('alt - this text is also included');
      }
    });

    it('does not perform inclusion when forcing a 404 and no alt attribute is present', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/alt/no-alt.html');

      try {
        await driver.wait(until.elementLocated(By.id('alt-included')), smallTimeout);
      } catch (error) {
        expect(error.name).toBe('TimeoutError');
      }
    });

    it('does not perform inclusion when predicate fails, no when-false-src and forcing a 404 in alt src', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/alt/when-fail-no-when-false-src-alt-error.html');

      try {
        await driver.wait(until.elementLocated(By.id('alt-included')), smallTimeout);
      } catch (error) {
        expect(error.name).toBe('TimeoutError');
      }
    });

    it('does perform inclusion when predicate fails, no when-false-src and using a valid alt src', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/alt/when-fail-no-when-false-src-alt-pass.html');

      try {
        await driver.wait(until.elementLocated(By.id('default-included')), smallTimeout);
      } catch (error) {
        expect(error.name).toBe('TimeoutError');

        const cSelector = By.id('alt-included');
        await driver.wait(until.elementLocated(cSelector), timeout);

        const c = await driver.findElement(cSelector);
        const cText = await c.getText();

        expect(cText).toBe('alt - this text is included');
      }
    });

    it('does not perform inclusion when predicate fails, when-false-src fails and alt src fails', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/alt/when-fail-when-false-src-fail-alt-error.html');

      try {
        await driver.wait(until.elementLocated(By.id('default-included')), smallTimeout);
      } catch (error) {
        expect(error.name).toBe('TimeoutError');
      }
    });

    it('does perform inclusion when predicate fails, when-false-src fails and using a valid alt src', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/alt/when-fail-when-false-src-fail-alt-pass.html');

      try {
        await driver.wait(until.elementLocated(By.id('default-included')), smallTimeout);
      } catch (error) {
        expect(error.name).toBe('TimeoutError');

        const cSelector = By.id('alt-included');
        await driver.wait(until.elementLocated(cSelector), timeout);

        const c = await driver.findElement(cSelector);
        const cText = await c.getText();

        expect(cText).toBe('alt - this text is included');
      }
    });

    it('does not perform inclusion when predicate is met, no when-false-src and alt src fails', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/alt/when-pass-no-when-false-src-alt-error.html');

      try {
        await driver.wait(until.elementLocated(By.id('alt-included')), smallTimeout);
      } catch (error) {
        expect(error.name).toBe('TimeoutError');
      }
    });

    it('does perform inclusion when predicate is met, no when-false-src and using a valid alt src', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/alt/when-pass-no-when-false-src-alt-pass.html');

      try {
        await driver.wait(until.elementLocated(By.id('default-included')), smallTimeout);
      } catch (error) {
        expect(error.name).toBe('TimeoutError');

        const cSelector = By.id('alt-included');
        await driver.wait(until.elementLocated(cSelector), timeout);

        const c = await driver.findElement(cSelector);
        const cText = await c.getText();

        expect(cText).toBe('alt - this text is included');
      }
    });

    it('does not perform inclusion when predicate is met, when-false-src fails and alt src fails', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/alt/when-pass-when-false-src-fail-alt-error.html');

      try {
        await driver.wait(until.elementLocated(By.id('alt-included')), smallTimeout);
      } catch (error) {
        expect(error.name).toBe('TimeoutError');
      }
    });

    it('does perform inclusion when predicate is met, when-false-src fails and using a valid alt src', async () => {
      await driver.get('http://tabby-prickly-rule.glitch.me/static/alt/when-pass-when-false-src-fail-alt-pass.html');

      try {
        await driver.wait(until.elementLocated(By.id('default-included')), smallTimeout);
      } catch (error) {
        expect(error.name).toBe('TimeoutError');

        const cSelector = By.id('alt-included');
        await driver.wait(until.elementLocated(cSelector), timeout);

        const c = await driver.findElement(cSelector);
        const cText = await c.getText();

        expect(cText).toBe('alt - this text is included');
      }
    });

    // Media
    if (browser.browserName !== 'safari' && browser.version !== '10') {
      it('loads small fragment for small viewport', async () => {
        const viewport = driver.manage().window();
        await viewport.setSize(1024, 768); // width, height
        await driver.get('http://tabby-prickly-rule.glitch.me/static/media/');

        const a = await driver.findElement(By.id('a')).getText();

        expect(a.trim()).toBe('Small viewport');
      });
    }



    afterEach(async function(){
      if (process.env.IS_LOCAL === 'true') {
        return;
      } else {
        var title = this.currentTest.title,
          passed = (this.currentTest.state === 'passed') ? true : false;

        await saucelabs.updateJob('gustaf_nk', driver.sessionID, {
          name: title,
          passed: passed
        });
      }

      if (log && browser.browserName === 'chrome') {
        driver.manage().logs()
          .get('browser')
          .then(v => v && v.length && console.log(v));
      }

      driver.quit();
    });

  });
});


================================================
FILE: __tests__/browsers-local.json
================================================
[
{"browserName":"chrome","platform":"OS X 10.11","version":"latest"},
{"browserName":"firefox","platform":"OS X 10.11","version":"latest"}
]


================================================
FILE: __tests__/browsers-remote.json
================================================
[
{"browserName":"chrome","platform":"Windows 10","version":"latest"},
{"browserName":"firefox","platform":"OS X 10.11","version":"latest"},
{"browserName":"safari","platform":"macOS 10.15","version":"latest"},

{"browserName":"chrome","platform":"Windows 10","version":"latest - 4"},
{"browserName":"firefox","platform":"OS X 10.11","version":"latest - 4"},
{"browserName":"safari","platform":"macOS 10.15","version":"latest - 4"},

{"browserName":"safari","platform":"macOS 10.12","version":"10"}
]


================================================
FILE: h-include.js
================================================

console.warn('Using h-include.js from the root folder is deprecated, please use lib/h-include.js instead');

// Reflect.construct polyfill adopted from https://github.com/WebReflection/classtrophobic-es5
/*! (C) 2017 Andrea Giammarchi - MIT Style License */
(function() {
  var sPO = Object.setPrototypeOf ||
          function (o, p) { o.__proto__ = p; return o; };
  var hasReflect = typeof Reflect === 'object';

  if (!hasReflect) {
    window.Reflect = {
      construct: function (Super, args, Constructor) {
        [].unshift.call(args, Super);
        var C = Super.bind.apply(Super, args);
        return sPO(new C, Constructor.prototype);
      }
    }
  }
})();

/*
h-include.js -- HTML Includes (version 4.5.0)

MIT Style License

Copyright (c) 2016-2019 Gustaf Nilsson Kotte <gustaf.nk@gmail.com>
Copyright (c) 2005-2012 Mark Nottingham <mnot@mnot.net>

------------------------------------------------------------------------------

See http://gustafnk.github.com/h-include/ for documentation.
*/

/*jslint indent: 2, browser: true, vars: true, nomen: true, loopfunc: true */

window.HInclude = {};
window.HInclude.HIncludeElement = window.HIncludeElement = (function() {

  var tagname = 'h-include';
  var TAGNAME = tagname.toUpperCase();
  var classprefix = 'include_';

  var config = window.HIncludeConfig;

  var buffer = [];
  var outstanding = 0;

  function showContent(element, req){
    var fragment = element.getAttribute('fragment') || 'body';
    if (req.status === 200 || (req.status === 304 && !element.isRefreshing)) {
      var container = element.createContainer.call(element, req);

      if (config && config.checkRecursion) {
        checkRecursion(element);
      }

      var node = element.extractFragment.call(element, container, fragment, req);
      element.replaceContent.call(element, node);
    }
    element.onEnd.call(element, req);
  }

  function setContentAsync(element, req) {
    showContent(element, req);
  }

  function setContentBuffered(element, req) {
    buffer.push([element, req]);
    outstanding -= 1;
    if (outstanding === 0) {
      showBufferedContent();
    }
  }

  function showBufferedContent() {
    while (buffer.length > 0) {
      var toShow = buffer.pop();

      try {
        showContent(toShow[0], toShow[1]);
      } catch(error) { // rethrow error without stopping the loop
        setTimeout(function() { throw error; });
      }
    }
  }

  var checkRecursion = function(element){
    // Check for recursion against current browser location
    if(element.getAttribute('src') === document.location.href) {
      throw new Error('Recursion not allowed');
    }

    // Check for recursion in ascendents
    var elementToCheck = element.parentNode;
    while (elementToCheck.parentNode) {
      if (elementToCheck.nodeName === TAGNAME) {

        if (element.getAttribute('src') === elementToCheck.getAttribute('src')) {
          throw new Error('Recursion not allowed');
        }
      }

      elementToCheck = elementToCheck.parentNode;
    }
  };

  var getUrl = function(element) {
    var whenFalseUrl = element.getAttribute('when-false-src');
    var whenCondition = whenFalseUrl && !element.conditionalInclusion.call(element, 'when');
    var mediaCondition = !element.conditionalInclusion.call(element, 'media');

    return getConditionalUrl(element, whenCondition, mediaCondition, element.altSrcInclude);
  };

  var getConditionalUrl = function(element, whenCondition, mediaCondition, altSrcInclude) {
    var url = element.getAttribute('src');
    var whenFalseUrl = element.getAttribute('when-false-src');
    var altUrl = element.getAttribute('alt');

    if(altSrcInclude) {
      url = altUrl;
    }
    else {
      if(whenCondition) {
        url = whenFalseUrl;
      }
      if(mediaCondition) {
        url = null;
      }
    }
    return url;
  };

  var useAltSrcOnError = function(element, req) {
    var altUrl = element.getAttribute('alt');

    return req.status !== 200 && req.status !== 304 && altUrl && !element.altSrcInclude;
  };

  var include = function(element, includeCallback) {
    var url = getUrl(element);
    if(!url) {
      return;
    }

    var scheme = url.substring(0, url.indexOf(':'));
    if (scheme.toLowerCase() === 'data') {
      throw new Error('data URIs are not allowed');
    }

    var req = new XMLHttpRequest();

    // Check if `withCredentials` should be true
    var withCredentialsAttribute = element.getAttribute('with-credentials');
    if (withCredentialsAttribute === '' || withCredentialsAttribute === 'true') {
      req.withCredentials = true;
    }

    outstanding += 1;
    req.onreadystatechange = function () {
      if (req.readyState === 4) {
        if(useAltSrcOnError(element, req)) {
          element.altSrcInclude = true;
          outstanding -= 1;
          include(element, includeCallback);
        } else {
          includeCallback(element, req);
        }
      }
    };
    try {
      req.open('GET', url, true);
      req.send('');
    } catch (e) {
      outstanding -= 1;
    }
  };

  var proto = Object.create(HTMLElement.prototype);

  function getPredicate(identifier, context) {
    var namespaces = identifier.split('.');
    var func = namespaces.pop();
    for (var i = 0; i < namespaces.length; i++) {
      context = context[namespaces[i]];
    }
    return context[func];
  }

  proto.conditionalInclusion = function(type) {
    switch (type) {
      case 'when':
        return conditionalWhen(this);
      case 'media':
        return conditionalMedia(this);
      default:
        return false;
    }
  };

  var conditionalWhen = function(element) {
    var when = element.getAttribute('when');
    if(when) {
      var predicate = getPredicate(when, window);
      if(predicate) {
        return predicate();
      } else {
        throw new Error('Predicate function not found');
      }
    }
  };

  var conditionalMedia = function(element) {
    var media = element.getAttribute('media');
    if (media && window.matchMedia && !window.matchMedia(media).matches) {
      return false;
    }
    return true;
  };

  proto.createContainer = function(req){
    var container = document.implementation.createHTMLDocument(' ').documentElement;
    container.innerHTML = req.responseText;

    return container;
  };

  proto.extractFragment = function(container, fragment, req) {
    var node = container.querySelector(fragment);

    if (!node) {
      throw new Error('Did not find fragment in response');
    }

    return node;
  };

  proto.replaceContent = function(node) {
    this.innerHTML = node.innerHTML;
  };

  proto.onEnd = function(req) {
    var tokens = this.className.split(/\s+/);
    var otherClasses = tokens.filter(function(token){
      return !token.match(/^include_\d+$/i) && !token.match(/^included/i);
    }).join(' ');

    this.className = otherClasses + (otherClasses ? ' ' : '') +
      'included ' + classprefix + req.status;

    this.altSrcInclude = false;
    this.isRefreshing = false;
  };

  proto.connectedCallback = function() {
    var mode = config && config.mode || 'buffered';

    var callback;
    if (mode === 'async') {
      callback = setContentAsync;
    } else if (mode === 'buffered') {
      callback = setContentBuffered;
      var timeout = config && config.timeout || 2500;
      setTimeout(showBufferedContent, timeout);
    }

    include(this, callback);
  };

  var refresh = function() {
    this.isRefreshing = true;

    var callback = setContentBuffered;
    include(this, callback);
  };

  proto.refresh = refresh;

  // `customElements.define()` requires `class HIncludeElement extends HTMLElement`.
  // But that would be a syntax error in older browsers. This is our work-around.
  // See https://medium.com/@robertgrosse/how-es6-classes-really-work-and-how-to-build-your-own-fd6085eb326a
  var HIncludeElement = function() {
    return Reflect.construct(HTMLElement, arguments, HIncludeElement);
  };
  HIncludeElement.prototype = proto;
  customElements.define(tagname, HIncludeElement);
  return HIncludeElement;
})();


================================================
FILE: lib/h-include-extensions.js
================================================
/*jslint indent: 2, browser: true, vars: true, nomen: true, loopfunc: true */

// Only loads on refresh(), to be used with initLazyLoad (below)
window.HInclude.HIncludeLazyElement = (function() {
  var proto = Object.create(HInclude.HIncludeElement.prototype);

  proto.connectedCallback = function(){};

  var HIncludeLazyElement = function() {
    return Reflect.construct(HTMLElement, arguments, HIncludeLazyElement);
  };
  HIncludeLazyElement.prototype = proto;

  customElements.define('h-include-lazy', HIncludeLazyElement);
  return HIncludeLazyElement;
})();

// Imports resource fragments (containing links to scripts and styles)
window.HInclude.HImportElement = (function() {
  var proto = Object.create(HInclude.HIncludeElement.prototype);

  proto.createContainer = function(req){
    var container = document.implementation.createHTMLDocument(' ').documentElement;
    container.innerHTML = req.responseText;

    var importableElements =
      Array.prototype.slice.call(container.querySelectorAll('script, link'));

    var urls = importableElements.map(function(element) {
      if (element.tagName === 'SCRIPT') {
        return element.src;
      } else if (
          element.tagName === 'LINK' &&
          element.rel &&
          element.rel.toLowerCase() === 'stylesheet') {
        return element.href;
      }
    }).filter(function(url){ return !!url; });

    HInclude.loadResources(urls);

    return container;
  };

  proto.replaceContent = function(node) {};

  var HImportElement = function() {
    return Reflect.construct(HTMLElement, arguments, HImportElement);
  };
  HImportElement.prototype = proto;

  customElements.define('h-import', HImportElement);
  return HImportElement;
})();

// Import resource fragments only on refresh(), to be used with initLazyLoad (below)
window.HInclude.HImportLazyElement = (function() {
  var proto = Object.create(HInclude.HImportElement.prototype);

  proto.connectedCallback = function(){};

  var HImportLazyElement = function() {
    return Reflect.construct(HTMLElement, arguments, HImportLazyElement);
  };
  HImportLazyElement.prototype = proto;

  customElements.define('h-import-lazy', HImportLazyElement);
  return HImportLazyElement;
})();

// Navigate within included content by handling link clicks
window.HInclude.HIncludeNavigateElement = (function() {
  var getElement = function(elementArg, nodeName) {
    var element;
    element = elementArg;
    while (element.parentNode && element.nodeName !== nodeName) {
      element = element.parentNode;
    }

    if (element.nodeName === nodeName) {
      return element;
    }
  };

  var getLink = function(element) {
    var link = getElement(element, 'A');

    if (link && link.href.length !== 0) {
      return link;
    }
  };

  var getHinclude = function(element) {
    return getElement(element, 'H-INCLUDE-NAVIGATE');
  };

  var handle = function(e) {
    var link = getLink(e.target);

    if (!link) return;

    // Detect target attribute
    var targetAttribute = link.getAttribute('target');
    if (targetAttribute === '_top') {
      // Treat as regular link
      return;
    }

    // Navigate
    var href = link.href;
    if (!href) return;

    var hElement = getHinclude(e.target);
    hElement.setAttribute('src', href);
    hElement.refresh();

    e.preventDefault();
  };

  var registerNavigation = function(element) {
    element.addEventListener('click', handle, true);
  };

  var proto = Object.create(HInclude.HIncludeElement.prototype);

  proto.connectedCallback = function(){
    HIncludeElement.prototype.connectedCallback.apply(this, arguments); // call super

    registerNavigation(this);
  };

  var HIncludeNavigateElement = function() {
    return Reflect.construct(HTMLElement, arguments, HIncludeNavigateElement);
  };
  HIncludeNavigateElement.prototype = proto;

  customElements.define('h-include-navigate', HIncludeNavigateElement);
  return HIncludeNavigateElement;
})();

// Lazy load elements using IntersectionObserver 
window.HInclude.initLazyLoad = function(selectorArg, configArg){
  var selector = selectorArg || 'h-include-lazy, h-import-lazy';
  var elements = Array.prototype.slice.call(document.querySelectorAll(selector));

  // When IntersectionObserver is absent, load eagerly instead
  if (!('IntersectionObserver' in window)) {
    [].forEach.call(elements, function(element) {
      element.refresh();
    });
    return;
  }

  var config = {
    root: configArg && configArg.root || null,
    rootMargin: configArg && configArg.rootMargin || '400px 0px',
    threshold: configArg && configArg.threshold || 0.01 // 1% of the target is visible
  };

  var observer = new IntersectionObserver(onIntersection, config);
  [].forEach.call(elements, function(element) {
    observer.observe(element);
  });

  function onIntersection(entries) {
    entries.forEach(function(entry) {
      if (entry.intersectionRatio > 0) {
        observer.unobserve(entry.target);
        entry.target.refresh();
      }
    });
  }
};

// Load an array of script and stylesheet resources (to be overridden)
// By default, loadjs (https://github.com/muicss/loadjs) is used
window.HInclude.loadResources = function(urls){
  loadjs(urls, {
    async: false,
  });
}


================================================
FILE: lib/h-include.js
================================================
// Reflect.construct polyfill adopted from https://github.com/WebReflection/classtrophobic-es5
/*! (C) 2017 Andrea Giammarchi - MIT Style License */
(function() {
  var sPO = Object.setPrototypeOf ||
          function (o, p) { o.__proto__ = p; return o; };
  var hasReflect = typeof Reflect === 'object';

  if (!hasReflect) {
    window.Reflect = {
      construct: function (Super, args, Constructor) {
        [].unshift.call(args, Super);
        var C = Super.bind.apply(Super, args);
        return sPO(new C, Constructor.prototype);
      }
    }
  }
})();

/*
h-include.js -- HTML Includes (version 4.5.0)

MIT Style License

Copyright (c) 2016-2019 Gustaf Nilsson Kotte <gustaf.nk@gmail.com>
Copyright (c) 2005-2012 Mark Nottingham <mnot@mnot.net>

------------------------------------------------------------------------------

See http://gustafnk.github.com/h-include/ for documentation.
*/

/*jslint indent: 2, browser: true, vars: true, nomen: true, loopfunc: true */

window.HInclude = {};
window.HInclude.HIncludeElement = window.HIncludeElement = (function() {

  var tagname = 'h-include';
  var TAGNAME = tagname.toUpperCase();
  var classprefix = 'include_';

  var config = window.HIncludeConfig;

  var buffer = [];
  var outstanding = 0;

  function showContent(element, req){
    var fragment = element.getAttribute('fragment') || 'body';
    if (req.status === 200 || (req.status === 304 && !element.isRefreshing)) {
      var container = element.createContainer.call(element, req);

      if (config && config.checkRecursion) {
        checkRecursion(element);
      }

      var node = element.extractFragment.call(element, container, fragment, req);
      element.replaceContent.call(element, node);
    }
    element.onEnd.call(element, req);
  }

  function setContentAsync(element, req) {
    showContent(element, req);
  }

  function setContentBuffered(element, req) {
    buffer.push([element, req]);
    outstanding -= 1;
    if (outstanding === 0) {
      showBufferedContent();
    }
  }

  function showBufferedContent() {
    while (buffer.length > 0) {
      var toShow = buffer.pop();

      try {
        showContent(toShow[0], toShow[1]);
      } catch(error) { // rethrow error without stopping the loop
        setTimeout(function() { throw error; });
      }
    }
  }

  var checkRecursion = function(element){
    // Check for recursion against current browser location
    if(element.getAttribute('src') === document.location.href) {
      throw new Error('Recursion not allowed');
    }

    // Check for recursion in ascendents
    var elementToCheck = element.parentNode;
    while (elementToCheck.parentNode) {
      if (elementToCheck.nodeName === TAGNAME) {

        if (element.getAttribute('src') === elementToCheck.getAttribute('src')) {
          throw new Error('Recursion not allowed');
        }
      }

      elementToCheck = elementToCheck.parentNode;
    }
  };

  var getUrl = function(element) {
    var whenFalseUrl = element.getAttribute('when-false-src');
    var whenCondition = whenFalseUrl && !element.conditionalInclusion.call(element, 'when');
    var mediaCondition = !element.conditionalInclusion.call(element, 'media');

    return getConditionalUrl(element, whenCondition, mediaCondition, element.altSrcInclude);
  };

  var getConditionalUrl = function(element, whenCondition, mediaCondition, altSrcInclude) {
    var url = element.getAttribute('src');
    var whenFalseUrl = element.getAttribute('when-false-src');
    var altUrl = element.getAttribute('alt');

    if(altSrcInclude) {
      url = altUrl;
    }
    else {
      if(whenCondition) {
        url = whenFalseUrl;
      }
      if(mediaCondition) {
        url = null;
      }
    }
    return url;
  };

  var useAltSrcOnError = function(element, req) {
    var altUrl = element.getAttribute('alt');

    return req.status !== 200 && req.status !== 304 && altUrl && !element.altSrcInclude;
  };

  var include = function(element, includeCallback) {
    var url = getUrl(element);
    if(!url) {
      return;
    }

    var scheme = url.substring(0, url.indexOf(':'));
    if (scheme.toLowerCase() === 'data') {
      throw new Error('data URIs are not allowed');
    }

    var req = new XMLHttpRequest();

    // Check if `withCredentials` should be true
    var withCredentialsAttribute = element.getAttribute('with-credentials');
    if (withCredentialsAttribute === '' || withCredentialsAttribute === 'true') {
      req.withCredentials = true;
    }

    outstanding += 1;
    req.onreadystatechange = function () {
      if (req.readyState === 4) {
        if(useAltSrcOnError(element, req)) {
          element.altSrcInclude = true;
          outstanding -= 1;
          include(element, includeCallback);
        } else {
          includeCallback(element, req);
        }
      }
    };
    try {
      req.open('GET', url, true);
      req.send('');
    } catch (e) {
      outstanding -= 1;
    }
  };

  var proto = Object.create(HTMLElement.prototype);

  function getPredicate(identifier, context) {
    var namespaces = identifier.split('.');
    var func = namespaces.pop();
    for (var i = 0; i < namespaces.length; i++) {
      context = context[namespaces[i]];
    }
    return context[func];
  }

  proto.conditionalInclusion = function(type) {
    switch (type) {
      case 'when':
        return conditionalWhen(this);
      case 'media':
        return conditionalMedia(this);
      default:
        return false;
    }
  };

  var conditionalWhen = function(element) {
    var when = element.getAttribute('when');
    if(when) {
      var predicate = getPredicate(when, window);
      if(predicate) {
        return predicate();
      } else {
        throw new Error('Predicate function not found');
      }
    }
  };

  var conditionalMedia = function(element) {
    var media = element.getAttribute('media');
    if (media && window.matchMedia && !window.matchMedia(media).matches) {
      return false;
    }
    return true;
  };

  proto.createContainer = function(req){
    var container = document.implementation.createHTMLDocument(' ').documentElement;
    container.innerHTML = req.responseText;

    return container;
  };

  proto.extractFragment = function(container, fragment, req) {
    var node = container.querySelector(fragment);

    if (!node) {
      throw new Error('Did not find fragment in response');
    }

    return node;
  };

  proto.replaceContent = function(node) {
    this.innerHTML = node.innerHTML;
  };

  proto.onEnd = function(req) {
    var tokens = this.className.split(/\s+/);
    var otherClasses = tokens.filter(function(token){
      return !token.match(/^include_\d+$/i) && !token.match(/^included/i);
    }).join(' ');

    this.className = otherClasses + (otherClasses ? ' ' : '') +
      'included ' + classprefix + req.status;

    this.altSrcInclude = false;
    this.isRefreshing = false;
  };

  proto.connectedCallback = function() {
    var mode = config && config.mode || 'buffered';

    var callback;
    if (mode === 'async') {
      callback = setContentAsync;
    } else if (mode === 'buffered') {
      callback = setContentBuffered;
      var timeout = config && config.timeout || 2500;
      setTimeout(showBufferedContent, timeout);
    }

    include(this, callback);
  };

  var refresh = function() {
    this.isRefreshing = true;

    var callback = setContentBuffered;
    include(this, callback);
  };

  proto.refresh = refresh;

  // `customElements.define()` requires `class HIncludeElement extends HTMLElement`.
  // But that would be a syntax error in older browsers. This is our work-around.
  // See https://medium.com/@robertgrosse/how-es6-classes-really-work-and-how-to-build-your-own-fd6085eb326a
  var HIncludeElement = function() {
    return Reflect.construct(HTMLElement, arguments, HIncludeElement);
  };
  HIncludeElement.prototype = proto;
  customElements.define(tagname, HIncludeElement);
  return HIncludeElement;
})();


================================================
FILE: package.json
================================================
{
  "name": "h-include",
  "version": "4.5.0",
  "homepage": "https://github.com/gustafnk/h-include",
  "repository": {
    "type": "git",
    "url": "https://github.com/gustafnk/h-include"
  },
  "author": "Gustaf Nilsson Kotte <gustaf.nk@gmail.com>",
  "description": "Declarative client-side inclusion for the web using Custom Elements",
  "main": "h-include.js",
  "keywords": [
    "web-components"
  ],
  "license": "MIT",
  "contributors": [
    {
      "name": "Mark Nottingham",
      "email": "mnot@mnot.com"
    },
    {
      "name": "Sean Hogan",
      "email": "shogun70@gmail.com"
    },
    {
      "name": "Nicolás Delfino",
      "email": "nicolas.delfino@tretton37.com"
    }
  ],
  "devDependencies": {
    "choma": "^1.2.1",
    "expect": "^23.6.0",
    "jshint": "*",
    "mocha": "^5.2.0",
    "prepend-file": "^1.3.1",
    "saucelabs": "^7.5.0",
    "selenium-webdriver": "^3.5.0",
    "simplehttpserver": "^0.2.1"
  },
  "engines": {
    "node": ">= 8.*"
  },
  "scripts": {
    "lint": "jshint lib/",
    "server": "simplehttpserver -p 8080 .",
    "test": "cd test; PORT=8080 make test",
    "local-tests": "npm run server > /dev/null 2>&1 & IS_LOCAL=true mocha -t 600000 __tests__/*-test.js",
    "remote-tests": "npm run server > /dev/null 2>&1 & mocha -t 180000 __tests__/*-test.js --require choma --retries 3",
    "test_killall": "npm test; killall node",
    "start": "npm run server"
  }
}


================================================
FILE: release-with-deprecation-warning.js
================================================
const fs = require('fs');
var prependFile = require('prepend-file');

fs.copyFileSync('./lib/h-include.js', './h-include.js');
prependFile.sync('./h-include.js', "\nconsole.warn('Using h-include.js from the root folder is deprecated, please use lib/h-include.js instead');\n\n");


================================================
FILE: static/alt/alt.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>test</title>
    <link type="text/css" rel="stylesheet" href="/static/style.css" />
    <script>
      this.customElements ||
        document.write(
          '<script src="//unpkg.com/document-register-element"><\x2fscript>'
        );
    </script>
    <script type="text/javascript" src="/lib/h-include.js"></script>
    <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
  </head>

  <body>
    <h1>h-include.js test page</h1>

    <h2 id="h">Request error - Alt</h2>

    <h-include src="nothing" alt="fragment3.html"></h-include>
    <h-include src="nothing" alt="fragment4.html"></h-include>

<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('alt-included');
  const aText = a.innerHTML;

  const b = document.getElementById('alt-2-included');
  const bText = b.innerHTML;

  expect(aText === 'alt - this text is included');
  expect(bText === 'alt - this text is also included');

}, 1000);
</script>
  </body>
</html>


================================================
FILE: static/alt/fragment.html
================================================
<span id="default-included" style="text-decoration: underline">default - this text is included</span>


================================================
FILE: static/alt/fragment2.html
================================================
<span id="when-false-src-included" style="text-decoration: underline">when-false-src - this text is included</span>

================================================
FILE: static/alt/fragment3.html
================================================
<span id="alt-included" style="text-decoration: underline">alt - this text is included</span>

================================================
FILE: static/alt/fragment4.html
================================================
<span id="alt-2-included" style="text-decoration: underline">alt - this text is also included</span>

================================================
FILE: static/alt/no-alt.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>test</title>
    <link type="text/css" rel="stylesheet" href="/static/style.css" />
    <script>
      this.customElements ||
        document.write(
          '<script src="//unpkg.com/document-register-element"><\x2fscript>'
        );
    </script>
    <script type="text/javascript" src="/lib/h-include.js"></script>
    <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
  </head>

  <body>
    <h1>h-include.js test page</h1>

    <h2 id="h">Request error - Alt</h2>

    <h-include src="nothing"></h-include>

<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('alt-included');

  expect(!a);
}, 1000);
</script>
  </body>
</html>


================================================
FILE: static/alt/when-fail-no-when-false-src-alt-error.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>test</title>
    <link type="text/css" rel="stylesheet" href="/static/style.css" />
    <script>
      this.customElements ||
        document.write(
          '<script src="//unpkg.com/document-register-element"><\x2fscript>'
        );
    </script>
    <script type="text/javascript" src="/lib/h-include.js"></script>
    <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
    <script>
      window.org = {
        project: {
          predicateFunction: function() {
            return false;
          }
        }
      };
    </script>
  </head>

  <body>
    <h1>h-include.js test page</h1>

    <h2 id="h">Request error - Alt</h2>

    <h-include
      src="nothing" when="org.project.predicateFunction" alt="nothing"></h-include>
  </body>
</html>


================================================
FILE: static/alt/when-fail-no-when-false-src-alt-pass.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>test</title>
    <link type="text/css" rel="stylesheet" href="/static/style.css" />
    <script>
      this.customElements ||
        document.write(
          '<script src="//unpkg.com/document-register-element"><\x2fscript>'
        );
    </script>
    <script type="text/javascript" src="/lib/h-include.js"></script>
    <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
    <script>
      window.org = {
        project: {
          predicateFunction: function() {
            return false;
          }
        }
      };
    </script>
  </head>

  <body>
    <h1>h-include.js test page</h1>

    <h2 id="h">Request error - Alt</h2>

    <h-include
      src="nothing" when="org.project.predicateFunction" alt="fragment3.html"></h-include>

<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('alt-included');
  const aText = a.innerHTML;

  expect(aText === 'alt - this text is included');
}, 1000);
</script>
  </body>
</html>


================================================
FILE: static/alt/when-fail-when-false-src-fail-alt-error.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>test</title>
    <link type="text/css" rel="stylesheet" href="/static/style.css" />
    <script>
      this.customElements ||
        document.write(
          '<script src="//unpkg.com/document-register-element"><\x2fscript>'
        );
    </script>
    <script type="text/javascript" src="/lib/h-include.js"></script>
    <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
    <script>
      window.org = {
        project: {
          predicateFunction: function() {
            return false;
          }
        }
      };
    </script>
  </head>

  <body>
    <h1>h-include.js test page</h1>

    <h2 id="h">Request error - Alt</h2>

    <h-include
      src="nothing" when="org.project.predicateFunction" when-false-src="nothing2" alt="nothing3"></h-include>

<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('alt-included');

  expect(!a);
}, 1000);
</script>
  </body>
</html>


================================================
FILE: static/alt/when-fail-when-false-src-fail-alt-pass.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>test</title>
    <link type="text/css" rel="stylesheet" href="/static/style.css" />
    <script>
      this.customElements ||
        document.write(
          '<script src="//unpkg.com/document-register-element"><\x2fscript>'
        );
    </script>
    <script type="text/javascript" src="/lib/h-include.js"></script>
    <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
    <script>
      window.org = {
        project: {
          predicateFunction: function() {
            return false;
          }
        }
      };
    </script>
  </head>

  <body>
    <h1>h-include.js test page</h1>

    <h2 id="h">Request error - Alt</h2>

    <h-include
      src="nothing" when="org.project.predicateFunction" when-false-src="nothing2" alt="fragment3.html"></h-include>

<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('alt-included');
  const aText = a.innerHTML;

  expect(aText === 'alt - this text is included');
}, 1000);
</script>
  </body>
</html>


================================================
FILE: static/alt/when-pass-no-when-false-src-alt-error.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>test</title>
    <link type="text/css" rel="stylesheet" href="/static/style.css" />
    <script>
      this.customElements ||
        document.write(
          '<script src="//unpkg.com/document-register-element"><\x2fscript>'
        );
    </script>
    <script type="text/javascript" src="/lib/h-include.js"></script>
    <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
    <script>
      window.org = {
        project: {
          predicateFunction: function() {
            return true;
          }
        }
      };
    </script>
  </head>

  <body>
    <h1>h-include.js test page</h1>

    <h2 id="h">Request error - Alt</h2>

    <h-include
      src="nothing" when="org.project.predicateFunction" alt="nothing"></h-include>

<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('alt-included');

  expect(!a);
}, 1000);
</script>
  </body>
</html>


================================================
FILE: static/alt/when-pass-no-when-false-src-alt-pass.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>test</title>
    <link type="text/css" rel="stylesheet" href="/static/style.css" />
    <script>
      this.customElements ||
        document.write(
          '<script src="//unpkg.com/document-register-element"><\x2fscript>'
        );
    </script>
    <script type="text/javascript" src="/lib/h-include.js"></script>
    <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
    <script>
      window.org = {
        project: {
          predicateFunction: function() {
            return true;
          }
        }
      };
    </script>
  </head>

  <body>
    <h1>h-include.js test page</h1>

    <h2 id="h">Request error - Alt</h2>

    <h-include
      src="nothing" when="org.project.predicateFunction" alt="fragment3.html"></h-include>

<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('alt-included');
  const aText = a.innerHTML;

  expect(aText === 'alt - this text is included');
}, 1000);
</script>
  </body>
</html>


================================================
FILE: static/alt/when-pass-when-false-src-fail-alt-error.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>test</title>
    <link type="text/css" rel="stylesheet" href="/static/style.css" />
    <script>
      this.customElements ||
        document.write(
          '<script src="//unpkg.com/document-register-element"><\x2fscript>'
        );
    </script>
    <script type="text/javascript" src="/lib/h-include.js"></script>
    <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
    <script>
      window.org = {
        project: {
          predicateFunction: function() {
            return true;
          }
        }
      };
    </script>
  </head>

  <body>
    <h1>h-include.js test page</h1>

    <h2 id="h">Request error - Alt</h2>

    <h-include
      src="nothing" when="org.project.predicateFunction" when-false-src="nothing2" alt="nothing3"></h-include>

<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('alt-included');

  expect(!a);
}, 1000);
</script>
  </body>
</html>


================================================
FILE: static/alt/when-pass-when-false-src-fail-alt-pass.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>test</title>
    <link type="text/css" rel="stylesheet" href="/static/style.css" />
    <script>
      this.customElements ||
        document.write(
          '<script src="//unpkg.com/document-register-element"><\x2fscript>'
        );
    </script>
    <script type="text/javascript" src="/lib/h-include.js"></script>
    <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
    <script>
      window.org = {
        project: {
          predicateFunction: function() {
            return true;
          }
        }
      };
    </script>
  </head>

  <body>
    <h1>h-include.js test page</h1>

    <h2 id="h">Request error - Alt</h2>

    <h-include
      src="nothing" when="org.project.predicateFunction" when-false-src="nothing2" alt="fragment3.html"></h-include>

<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('alt-included');
  const aText = a.innerHTML;

  expect(aText === 'alt - this text is included');
}, 1000);
</script>
  </body>
</html>


================================================
FILE: static/basic/fragment-2.html
================================================
<span id="included-2" style="text-decoration: underline">this text overwrote what was just there</span>

================================================
FILE: static/basic/fragment.html
================================================
<span id="included-1" style="text-decoration: underline">this text is included</span>

================================================
FILE: static/basic/index.html
================================================
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<title>h-include Tests</title>
	<link type="text/css" rel="stylesheet" href="/static/style.css">
  <script type="text/javascript">
    HIncludeConfig = { timeout: 10000 };
  </script>
	<script>this.customElements||document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');</script>
	<script type="text/javascript" src="/lib/h-include.js"></script>
	<style type="text/css">
	.error_text { display: none; }
	.include_404 .error_404 { display: inline; text-decoration: underline; }
	</style>
</head>
<body>

<h1>h-include.js test page</h1>

<h2 id="h">Basic Include</h2>

<p id="a" name="a"><h-include src="404.html" alt="fragment.html"></h-include></p>

<h2>Default Content</h2>

<p id="b"><h-include src="404.html" alt="fragment-2.html">this content will be overwritten by the included content</h-include>.</p>

<h2>Error Handling</h2>

<p id="c"><h-include src="nothing"><span class="error_text error_404">this content is shown because there was a 404</span><span class="error_text error_500">this content is shown because there was a 500</span></h-include>.</p>

<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('included-1');
  const b = document.getElementById('included-2');

  const aText = a.innerHTML;
  const bText = b.innerHTML;

  expect(aText === 'this text is included');
  expect(bText === 'this text overwrote what was just there');
}, 1000);
</script>

</body>
</html>

================================================
FILE: static/basic-async/fragment-2.html
================================================
<span id="included-2" style="text-decoration: underline">this text overwrote what was just there</span>

================================================
FILE: static/basic-async/fragment.html
================================================
<span id="included-1" style="text-decoration: underline">this text is included</span>

================================================
FILE: static/basic-async/index.html
================================================
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<title>h-include Tests</title>
	<link type="text/css" rel="stylesheet" href="/static/style.css">
  <script type="text/javascript">
    HIncludeConfig = { mode: 'async' };
  </script>
	<script>this.customElements||document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');</script>
	<script type="text/javascript" src="/lib/h-include.js"></script>
	<style type="text/css">
	.error_text { display: none; }
	.include_404 .error_404 { display: inline; text-decoration: underline; }
	</style>
</head>
<body>

<h1>h-include.js test page</h1>

<h2 id="h">Basic Include</h2>

<p id="a" name="a"><h-include src="fragment.html"></h-include></p>

<h2>Default Content</h2>

<p id="b"><h-include src="fragment-2.html">this content will be overwritten by the included content</h-include>.</p>

<h2>Error Handling</h2>

<p id="c"><h-include src="nothing"><span class="error_text error_404">this content is shown because there was a 404</span><span class="error_text error_500">this content is shown because there was a 500</span></h-include>.</p>

<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('included-1');
  const b = document.getElementById('included-2');

  const aText = a.innerHTML;
  const bText = b.innerHTML;

  expect(aText === 'this text is included');
  expect(bText === 'this text overwrote what was just there');
}, 1000);
</script>

</body>
</html>

================================================
FILE: static/expect.js
================================================
var i = 0;
window.expect = function(passed, actual){
  console.log('Test', i, 'passed?', passed, !passed ? actual : '');
  // alert('Test ' + i + ' passed? ' + passed + ' ' + (!passed ? actual : ''));
  i++;  
}


================================================
FILE: static/fragment-extraction/full-page.html
================================================
<!DOCTYPE html>
<html>
<head>
	<title>A page with a fragment</title>
</head>
<body>

<h1>A page with a fragment</h1>

<div class="container">

<h2>Secondary header in fragment</h2>

<p id="a">Paragraph in fragment</p>
</div>

</body>
</html>

================================================
FILE: static/fragment-extraction/index.html
================================================
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<title>h-include Tests</title>
	<link type="text/css" rel="stylesheet" href="/static/style.css">
	<script>this.customElements||document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');</script>
	<script type="text/javascript" src="/lib/h-include.js"></script>
	<style type="text/css">
	.error_text { display: none; }
	.include_404 .error_404 { display: inline; text-decoration: underline; }
	</style>
</head>
<body>

<h1>h-include.js test page</h1>

<h2 id="h">Fragment</h2>

<p><h-include src="full-page.html" fragment=".container"></h-include></p>

</body>
</html>

================================================
FILE: static/index.html
================================================
<h1>Links for visual tests</h1>

<ul>
  <li><a href="basic/index.html">basic</a></li>
  <li><a href="basic-async/index.html">basic async</a></li>
  <li><a href="lazy-extension/index.html">lazy extension</a></li>
  <li><a href="none/index.html">none</a></li>
  <li><a href="when/when-pass-use-src.html">when 1</a></li>
  <li><a href="when/when-fail.html">when 2 (fails)</a></li>
  <li><a href="when/when-fail-if-when-false-src.html">when 3</a></li>
  <li><a href="when/when-fail-if-when-false-src.html">when 4</a></li>
  <li><a href="when/when-fail-if-when-false-src.html">when 5</a></li>
  <li><a href="alt/alt.html">alt 1</a></li>
  <li><a href="alt/no-alt.html">alt 2</a></li>
  <li><a href="alt/when-fail-no-when-false-src-alt-pass.html">alt 3</a></li>
  <li><a href="alt/when-fail-when-false-src-fail-alt-error.html">alt 4</a></li>
  <li><a href="alt/when-fail-when-false-src-fail-alt-pass.html">alt 5</a></li>
  <li><a href="alt/when-pass-no-when-false-src-alt-error.html">alt 6</a></li>
  <li><a href="alt/when-pass-no-when-false-src-alt-pass.html">alt 7</a></li>
  <li><a href="alt/when-pass-when-false-src-fail-alt-error.html">alt 8</a></li>
  <li><a href="alt/when-pass-when-false-src-fail-alt-pass.html">alt 9</a></li>
</ul>



================================================
FILE: static/lazy-extension/fragment-3.html
================================================
<span id="included-3" style="text-decoration: underline">this text is included 3</span>

================================================
FILE: static/lazy-extension/fragment.html
================================================
<span id="included-1" style="text-decoration: underline">this text is included</span>

================================================
FILE: static/lazy-extension/index.html
================================================
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>h-include Tests</title>
  <link type="text/css" rel="stylesheet" href="/static/style.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/loadjs/3.5.5/loadjs.min.js"></script>
  <script>this.customElements||document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');</script>
  <script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
  <script type="text/javascript" src="/lib/h-include.js"></script>
  <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
  <style type="text/css">
  .error_text { display: none; }
  .include_404 .error_404 { display: inline; text-decoration: underline; }
  .counter-container { position: fixed; top: 20px; right: 20px; }
  h-include-lazy { display: block; }
  </style>
  <script>
  window.addEventListener('load', function() {
    HInclude.initLazyLoad('h-include-lazy, h-import-lazy');
  });
  </script>

</head>
<body>

<h1>h-include.js test page</h1>

<h2 id="h">Lazy loading</h2>

<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment-3.html"></h-include-lazy>

<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>

<h-include-lazy src="fragment.html"></h-include-lazy>

<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>

Sooon....
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>

<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>

<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>

Soon an explosion of includes....

<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>

<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>
<h-include-lazy src="fragment.html"></h-include-lazy>


<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>

<h-import-lazy src="/static/import-extension/resource-fragment.html"></h-import-lazy>


<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>

Fin.

<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('included-3');
  const aText = a.innerHTML;

  expect(aText === 'this text is included 3');
}, 1000);
</script>

</body>
</html>

================================================
FILE: static/media/index.html
================================================
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<title>h-include Tests</title>
	<link type="text/css" rel="stylesheet" href="/static/style.css">
	<script>this.customElements||document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');</script>
	<script type="text/javascript" src="/lib/h-include.js"></script>
	<style type="text/css">
	.error_text { display: none; }
	.include_404 .error_404 { display: inline; text-decoration: underline; }
	</style>
</head>
<body>

<h1>h-include.js test page</h1>

<h2 id="h">Media Include</h2>

<p id="a" name="a"><h-include media="screen and (max-width: 1124px)" src="small.html"></h-include><h-include media="screen and (min-width: 1125px)" src="large.html"></h-include></p>


<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('a');
  const aText = a.textContent.trim();

  expect(aText === 'Small viewport', aText);
}, 1000);
</script>
</body>
</html>


================================================
FILE: static/media/large.html
================================================
Large viewport


================================================
FILE: static/media/small.html
================================================
Small viewport


================================================
FILE: static/navigate-extension/1.html
================================================
<div id="a"><a href="2.html"><i class="link">Click</i> here <b>now</b></a></div>

================================================
FILE: static/navigate-extension/2.html
================================================
<div id="b">
<a href="1.html">Back</a>
<br><br>
A box
<br>
With several lines
<br>
With <a href="3.html">another <i class="link">link</i></a>
<br>
And <a href="https://github.com/gustafnk/h-include" target="_top">an external link</a>
</div>

================================================
FILE: static/navigate-extension/3.html
================================================
<div>
<a href="2.html">Back</a>
<br><br>
<div id="c">This is the last box. Goodbye.</div>
</div>

================================================
FILE: static/navigate-extension/extract-fragment/1.html
================================================
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>h-include Tests</title>
  <link type="text/css" rel="stylesheet" href="/static/style.css">
</head>
<body>

<h1>h-include-navigate.js navigation test page</h1>

<div class="container"><a href="2.html"><i>Click</i> here <b>now</b></a></div>

</body>
</html>

================================================
FILE: static/navigate-extension/extract-fragment/2.html
================================================
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>h-include Tests</title>
  <link type="text/css" rel="stylesheet" href="/static/style.css">
</head>
<body>

<h1>h-include-navigate.js navigation test page</h1>

<div class="container">
<a href="1.html">Back</a>
<br><br>
A box
<br>
With several lines
<br>
With <a href="3.html">another link</a>
<br>
And <a href="https://github.com/gustafnk/h-include" target="_top">an external link</a>
</div>

</body>
</html>

================================================
FILE: static/navigate-extension/extract-fragment/3.html
================================================
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>h-include Tests</title>
  <link type="text/css" rel="stylesheet" href="/static/style.css">
</head>
<body>

<h1>h-include-navigate.js navigation test page</h1>

<div class="container">
<a href="2.html">Back</a>
<br><br>
This is the last box. Goodbye.
</div>

</body>
</html>

================================================
FILE: static/navigate-extension/extract-fragment/index.html
================================================
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>h-include Tests</title>
  <link type="text/css" rel="stylesheet" href="/static/style.css">
  <script>this.customElements||document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');</script>
  <script type="text/javascript" src="/lib/h-include.js"></script>
  <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
  <style type="text/css">
  .error_text { display: none; }
  .include_404 .error_404 { display: inline; text-decoration: underline; }
  .box { border-style: dashed; border-color: black; width: 200px; padding: 50px;}
  </style>
</head>
<body>

<h1>h-include-navigate.js navigation test page</h1>

<h2 id="h">Navigate within element and extract fragment from full document</h2>

<p class="box" id="box-1"><h-include-navigate src="1.html" fragment=".container"></h-include-navigate></p>
<p class="box" id="box-2"><h-include-navigate src="1.html" fragment=".container"></h-include-navigate></p>
<p class="box" id="box-3"><h-include-navigate src="1.html" fragment=".container"></h-include-navigate></p>

</body>
</html>

================================================
FILE: static/navigate-extension/index.html
================================================
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>h-include Tests</title>
  <link type="text/css" rel="stylesheet" href="/static/style.css">
  <script>this.customElements||document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');</script>
  <script type="text/javascript" src="/lib/h-include.js"></script>
  <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
  <style type="text/css">
  .error_text { display: none; }
  .include_404 .error_404 { display: inline; text-decoration: underline; }
  .box { border-style: dashed; border-color: black; width: 200px; padding: 50px;}
  </style>
</head>
<body>

<h1>h-include-navigate.js navigation test page</h1>

<h2 id="h">Fragment</h2>

<p class="box" id="box-1"><h-include-navigate src="1.html"></h-include-navigate></p>
<p class="box" id="box-2"><h-include-navigate src="1.html"></h-include-navigate></p>
<p class="box" id="box-3"><h-include-navigate src="1.html"></h-include-navigate></p>

</body>
</html>

================================================
FILE: static/navigate-extension/nested/1.html
================================================
<div><a href="2.html"><i>Click</i> here <b>now</b></a></div>

================================================
FILE: static/navigate-extension/nested/2.html
================================================
<div>
<a href="1.html">Back</a>
<br><br>
A box
<br>
With several lines
<br>
With <a href="3.html">another link</a>
<br>
And <a href="https://github.com/gustafnk/h-include" target="_top">an external link</a>
</div>

================================================
FILE: static/navigate-extension/nested/3.html
================================================
<div>
<a href="2.html">Back</a>
<br><br>
This is the last box. Goodbye.
</div>

================================================
FILE: static/navigate-extension/nested/index.html
================================================
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>h-include Tests</title>
  <link type="text/css" rel="stylesheet" href="/static/style.css">
  <script>this.customElements||document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');</script>
  <script type="text/javascript" src="/lib/h-include.js"></script>
  <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
  <style type="text/css">
  .error_text { display: none; }
  .include_404 .error_404 { display: inline; text-decoration: underline; }
  .box { border-style: dashed; border-color: black; width: 200px; padding: 50px;}
  .large-box { border-style: dashed; border-color: black; width: 400px; padding: 50px;}
  </style>
</head>
<body>

<h1><code>h-include-navigate</code> test page</h1>

<h2 id="h">Navigate within nested <code>h-include-navigate</code></h2>

<p class="box" id="box-1"><h-include-navigate src="1.html"></h-include-navigate></p>

<p class="large-box" id="box-2"><h-include-navigate src="inner.html"></h-include-navigate></p>
<p class="large-box" id="box-3"><h-include-navigate src="inner.html"></h-include-navigate></p>

</body>
</html>

================================================
FILE: static/navigate-extension/nested/inner.html
================================================
<h2 id="h">Inner container (included)</h2>

<p class="box" id="box-1"><h-include-navigate src="1.html"></h-include-navigate></p>
<p class="box" id="box-2"><h-include-navigate src="1.html"></h-include-navigate></p>
<p class="box" id="box-3"><h-include-navigate src="1.html"></h-include-navigate></p>

================================================
FILE: static/none/index.html
================================================
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<title>h-include Tests</title>
	<link type="text/css" rel="stylesheet" href="/static/style.css">
	<script>this.customElements||document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');</script>
	<script type="text/javascript" src="/lib/h-include.js"></script>
	<style type="text/css">
	.error_text { display: none; }
	.include_404 .error_404 { display: inline; text-decoration: underline; }
	</style>
</head>
<body>

<h1>h-include.js test page</h1>

<h2 id="h">No Includes</h2>

<p id="a" name="a">1st para</p>


<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('a');
  const aText = a.innerHTML;

  expect(aText === '1st para');
}, 1000);
</script>
</body>
</html>

================================================
FILE: static/recursion-not-allowed/index.html
================================================
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<title>h-include Tests</title>
	<link type="text/css" rel="stylesheet" href="/static/style.css">
  <script type="text/javascript">
    HIncludeConfig = { checkRecursion: true };
  </script>
	<script>this.customElements||document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');</script>
	<script type="text/javascript" src="/lib/h-include.js"></script>
	<style type="text/css">
	.error_text { display: none; }
	.include_404 .error_404 { display: inline; text-decoration: underline; }
	</style>
</head>
<body>

<h1>h-include.js test page</h1>

<h2 id="h">Recursion not allowed</h2>

<!-- works with [root] relative urls as well -->

<h-include src="recursive-fragment.html"></h-include>

<div id="result"/>

<script>
setTimeout(function(){
  var numberOfIncludes = document.querySelectorAll('.recursive').length;
  document.getElementById('result').innerHTML =
    '<div id="a">' + numberOfIncludes + '</div>';
}, 1000);
</script>

</body>
</html>


================================================
FILE: static/recursion-not-allowed/recursive-fragment.html
================================================
<p>
  <div class="recursive">Recursive</div>
  <h-include src="recursive-fragment.html"></h-include>
</p>

================================================
FILE: static/style.css
================================================
body {
  font-family: Helvetica, Arial, sans-serif;
}


================================================
FILE: static/visual-tests/domparser/body.html
================================================
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p>This is a full HTML document which contains HTML, HEAD and BODY tags.</p>
</body>
</html>



================================================
FILE: static/visual-tests/domparser/domparser.html
================================================
<!DOCTYPE html>
<html>
<head>
<script>this.customElements||document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');</script>
<script src="../../static/h-include.js"></script>
<style>
h-include { 
	display: block;
	border: 2px solid orange; 
}
h-include[status=pass] {
	border-color: green;
}
h-include[status=fail] {
	border-color: red;
}
</style>
</head>
<body>
<h1>DOMParser test</h1>
<p>This is a visual test page for using a DOMParser for all included content (even partial HTML documents).</p>
<p>Visual inspection isn't sufficient. 
<ul>
<li>
Check in the DOM Inspector that all expected content is inserted and no unexpected content is (e.g. &lt;body&gt; or &lt;main&gt; elements).
</li>
<li>
Check in the Console that no unexpected errors are thrown,
and that appropriate warnings are logged.
</li>
</ul>

<hr />

<script>
var hIncludes = document.getElementsByTagName('h-include');
var hIncludeIndex = 0;
</script>

<h2>Partial HTML document</h2>
<p>
<small>This is the backwards-compatibility case.</small>
<small>It should NOT insert a &lt;body&gt; element</small>
</p>
<p><h-include src="partial.html"></h-include></p>

<script>
hIncludes[hIncludeIndex].onSuccess = function() {
	var className = this.querySelector('body') ? 'fail' : 'pass';
	this.setAttribute('status', className);
}
hIncludeIndex++;
</script>

<hr />

<h2>Full HTML document</h2>
<p>
<small>It should insert "document.body.innerHTML"</small>
<small>It should NOT insert a &lt;body&gt; element</small>
</p>
<p><h-include src="body.html"></h-include></p>

<script>
hIncludes[hIncludeIndex].onSuccess = function() {
	var className = this.querySelector('body') ? 'fail' : 'pass';
	this.setAttribute('status', className);
}
hIncludeIndex++;
</script>

<hr />

<h2>Full HTML document with fragment</h2>
<p>
<small>It should insert "document.querySelector('main').innerHTML"</small>
<small>It should NOT insert a &lt;main&gt; element</small>
</p>
<p><h-include src="main.html" fragment="main"></h-include></p>

<script>
hIncludes[hIncludeIndex].onSuccess = function() {
	var className = this.querySelector('main') ? 'fail' : 'pass';
	this.setAttribute('status', className);
}
hIncludeIndex++;
</script>

<hr />

<h2>Full HTML document with fragment that is not found</h2>
<p>
<small>It should NOT insert ANYTHING because it fails to find the fragment</small>
</p>
<p><h-include src="body.html" fragment="main"></h-include></p>

<script>
hIncludes[hIncludeIndex].onSuccess = function() {
	var className = 'fail';
	this.setAttribute('status', className);
}
hIncludes[hIncludeIndex].setAttribute('status', 'pass');
hIncludeIndex++;
</script>

</body>
</html>



================================================
FILE: static/visual-tests/domparser/main.html
================================================
<!DOCTYPE html>
<html>
<body>
<p>This is a full HTML document which also contains a MAIN tag.</p>
<main>
<p>This is the &lt;main&gt; content</p>
</main>
</body>
</html>



================================================
FILE: static/visual-tests/domparser/partial.html
================================================
<p>This is a partial HTML document. It has no HTML, HEAD or BODY tags</p>



================================================
FILE: static/visual-tests/import-extension/index.html
================================================
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>h-include Tests</title>
  <link type="text/css" rel="stylesheet" href="/static/style.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/loadjs/3.5.5/loadjs.min.js"></script>
  <script>this.customElements||document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');</script>
  <script type="text/javascript" src="/lib/h-include.js"></script>
  <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
  <style type="text/css">
  .error_text { display: none; }
  .include_404 .error_404 { display: inline; text-decoration: underline; }
  .counter-container { position: fixed; top: 20px; right: 20px; }
  h-import { display: block; }
  </style>
</head>
<body>

<h1>h-include.js test page</h1>

<h-import src="resource-fragment.html"></h-import>

</body>
</html>

================================================
FILE: static/visual-tests/import-extension/resource-fragment.html
================================================
<script src="/static/import-extension/script-1.js"></script>
<link rel="stylesheet" href="/static/import-extension/styles-1.css" />
<script src="/static/import-extension/script-2.js"></script>
<link rel="stylesheet" href="/static/import-extension/styles-2.css" />


================================================
FILE: static/visual-tests/import-extension/script-1.js
================================================
console.log('Foo');


================================================
FILE: static/visual-tests/import-extension/script-2.js
================================================
console.log('Bar');


================================================
FILE: static/visual-tests/import-extension/styles-1.css
================================================
h1 {
  color: red;
}


================================================
FILE: static/visual-tests/import-extension/styles-2.css
================================================
h1 {
  color: green;
}


================================================
FILE: static/when/fragment.html
================================================
<span id="when-included" style="text-decoration: underline">when - this text is included</span>

================================================
FILE: static/when/fragment2.html
================================================
<span id="when-false-src-included" style="text-decoration: underline">when-false-src - this text is included</span>

================================================
FILE: static/when/when-fail-if-when-false-src.html
================================================
<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>test</title>
  <link type="text/css" rel="stylesheet" href="/static/style.css">
  <script>
    this.customElements || document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');
  </script>
  <script type="text/javascript" src="/lib/h-include.js"></script>
  <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
  <script>
    window.org = {
      project: {
        predicateFunction: function() {
          return false;
        }
      }
    }
  </script>
</head>

<body>

  <h1>h-include.js test page</h1>

  <h2 id="h">When / when-false-src - conditional inclusion</h2>

  <h-include src="fragment.html" when="org.project.predicateFunction" when-false-src="fragment2.html"></h-include>

<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('when-false-src-included');
  const aText = a.innerHTML;

  expect(aText === 'when-false-src - this text is included');
}, 1000);
</script>
</body>

</html>

================================================
FILE: static/when/when-fail.html
================================================
<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>test</title>
  <link type="text/css" rel="stylesheet" href="/static/style.css">
  <script>
    this.customElements || document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');
  </script>
  <script type="text/javascript" src="/lib/h-include.js"></script>
  <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
  <script>
    window.org = {
      project: {
        predicateFunction: function() {
          return false;
        }
      }
    }
  </script>
</head>

<body>

  <h1>h-include.js test page</h1>

  <h2 id="h">When / when-false-src - conditional inclusion</h2>

  <h-include src="fragment.html" when="org.project.predicateFunction"></h-include>

<!-- Legacy browser tests -->
<!-- Seems to reveal a bug... -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('when-included');

  expect(!a);
}, 1000);
</script>
</body>

</html>

================================================
FILE: static/when/when-pass-use-src.html
================================================
<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>test</title>
  <link type="text/css" rel="stylesheet" href="/static/style.css">
  <script>
    this.customElements || document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');
  </script>
  <script type="text/javascript" src="/lib/h-include.js"></script>
  <script type="text/javascript" src="/lib/h-include-extensions.js"></script>
  <script>
    window.org = {
      project: {
        predicateFunction: function() {
          return true;
        }
      }
    }
  </script>
</head>

<body>

  <h1>h-include.js test page</h1>

  <h2 id="h">When / when-false-src - conditional inclusion</h2>

  <h-include src="fragment.html" when="org.project.predicateFunction" when-false-src="fragment2.html"></h-include>



<!-- Legacy browser tests -->
<script src="../expect.js"></script>
<script type="text/javascript">
setTimeout(function(){
  const a = document.getElementById('when-included');
  const aText = a.innerHTML;

  expect(aText === 'when - this text is included');
}, 1000);
</script>
</body>

</html>
Download .txt
gitextract_u4czxxj4/

├── .github/
│   └── workflows/
│       └── main.yml
├── .gitignore
├── .jshintrc
├── .npmignore
├── EXTENDING.md
├── FAQ.md
├── LICENSE.md
├── README.md
├── __tests__/
│   ├── README.md
│   ├── browser-test.js
│   ├── browsers-local.json
│   └── browsers-remote.json
├── h-include.js
├── lib/
│   ├── h-include-extensions.js
│   └── h-include.js
├── package.json
├── release-with-deprecation-warning.js
└── static/
    ├── alt/
    │   ├── alt.html
    │   ├── fragment.html
    │   ├── fragment2.html
    │   ├── fragment3.html
    │   ├── fragment4.html
    │   ├── no-alt.html
    │   ├── when-fail-no-when-false-src-alt-error.html
    │   ├── when-fail-no-when-false-src-alt-pass.html
    │   ├── when-fail-when-false-src-fail-alt-error.html
    │   ├── when-fail-when-false-src-fail-alt-pass.html
    │   ├── when-pass-no-when-false-src-alt-error.html
    │   ├── when-pass-no-when-false-src-alt-pass.html
    │   ├── when-pass-when-false-src-fail-alt-error.html
    │   └── when-pass-when-false-src-fail-alt-pass.html
    ├── basic/
    │   ├── fragment-2.html
    │   ├── fragment.html
    │   └── index.html
    ├── basic-async/
    │   ├── fragment-2.html
    │   ├── fragment.html
    │   └── index.html
    ├── expect.js
    ├── fragment-extraction/
    │   ├── full-page.html
    │   └── index.html
    ├── index.html
    ├── lazy-extension/
    │   ├── fragment-3.html
    │   ├── fragment.html
    │   └── index.html
    ├── media/
    │   ├── index.html
    │   ├── large.html
    │   └── small.html
    ├── navigate-extension/
    │   ├── 1.html
    │   ├── 2.html
    │   ├── 3.html
    │   ├── extract-fragment/
    │   │   ├── 1.html
    │   │   ├── 2.html
    │   │   ├── 3.html
    │   │   └── index.html
    │   ├── index.html
    │   └── nested/
    │       ├── 1.html
    │       ├── 2.html
    │       ├── 3.html
    │       ├── index.html
    │       └── inner.html
    ├── none/
    │   └── index.html
    ├── recursion-not-allowed/
    │   ├── index.html
    │   └── recursive-fragment.html
    ├── style.css
    ├── visual-tests/
    │   ├── domparser/
    │   │   ├── body.html
    │   │   ├── domparser.html
    │   │   ├── main.html
    │   │   └── partial.html
    │   └── import-extension/
    │       ├── index.html
    │       ├── resource-fragment.html
    │       ├── script-1.js
    │       ├── script-2.js
    │       ├── styles-1.css
    │       └── styles-2.css
    └── when/
        ├── fragment.html
        ├── fragment2.html
        ├── when-fail-if-when-false-src.html
        ├── when-fail.html
        └── when-pass-use-src.html
Download .txt
SYMBOL INDEX (11 symbols across 3 files)

FILE: h-include.js
  function showContent (line 49) | function showContent(element, req){
  function setContentAsync (line 64) | function setContentAsync(element, req) {
  function setContentBuffered (line 68) | function setContentBuffered(element, req) {
  function showBufferedContent (line 76) | function showBufferedContent() {
  function getPredicate (line 182) | function getPredicate(identifier, context) {

FILE: lib/h-include-extensions.js
  function onIntersection (line 165) | function onIntersection(entries) {

FILE: lib/h-include.js
  function showContent (line 46) | function showContent(element, req){
  function setContentAsync (line 61) | function setContentAsync(element, req) {
  function setContentBuffered (line 65) | function setContentBuffered(element, req) {
  function showBufferedContent (line 73) | function showBufferedContent() {
  function getPredicate (line 179) | function getPredicate(identifier, context) {
Condensed preview — 79 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (103K chars).
[
  {
    "path": ".github/workflows/main.yml",
    "chars": 1166,
    "preview": "name: browser test\non: [push, workflow_dispatch]\njobs:\n    test:\n        runs-on: ubuntu-latest\n        name: Action Tes"
  },
  {
    "path": ".gitignore",
    "chars": 66,
    "preview": "static/error.png\nnpm-debug.log\nnode_modules/\nh-include\n\n.DS_Store\n"
  },
  {
    "path": ".jshintrc",
    "chars": 18,
    "preview": "{\n  \"expr\": true\n}"
  },
  {
    "path": ".npmignore",
    "chars": 115,
    "preview": "__tests__\nstatic\n.jshintrc\n.travis.yml\nEXTENDING.md\nFAQ.md\nfavicon.ico\nrelease-with-deprecation-warning.js\n.github\n"
  },
  {
    "path": "EXTENDING.md",
    "chars": 1800,
    "preview": "# Extending h-include\n\nExtending h-include is quite simple. Follow the pattern below and then look at the method table a"
  },
  {
    "path": "FAQ.md",
    "chars": 332,
    "preview": "# Frequently asked questions\n\n## Can I include fragments from other hostnames?\n\nYes, if the remote origin supports CORS "
  },
  {
    "path": "LICENSE.md",
    "chars": 1160,
    "preview": "MIT License\n\nCopyright (c) 2016-2019 Gustaf Nilsson Kotte <gustaf.nk@gmail.com>\nCopyright (c) 2005-2012 Mark Nottingham "
  },
  {
    "path": "README.md",
    "chars": 10593,
    "preview": "# h-include.js\n\nDeclarative client-side transclusion, using [Custom Elements V1](https://developers.google.com/web/funda"
  },
  {
    "path": "__tests__/README.md",
    "chars": 1382,
    "preview": "\nTests\n=====\n\nRequirements\n------------\n\n * node (version 7.6 or higher)\n * npm\n\nAfter this we can set up the project\n \n"
  },
  {
    "path": "__tests__/browser-test.js",
    "chars": 14299,
    "preview": "const path = require('path');\nconst fs = require('fs');\n\nconst expect = require('expect');\nconst { Builder, By, Key, unt"
  },
  {
    "path": "__tests__/browsers-local.json",
    "chars": 142,
    "preview": "[\n{\"browserName\":\"chrome\",\"platform\":\"OS X 10.11\",\"version\":\"latest\"},\n{\"browserName\":\"firefox\",\"platform\":\"OS X 10.11\","
  },
  {
    "path": "__tests__/browsers-remote.json",
    "chars": 501,
    "preview": "[\n{\"browserName\":\"chrome\",\"platform\":\"Windows 10\",\"version\":\"latest\"},\n{\"browserName\":\"firefox\",\"platform\":\"OS X 10.11\","
  },
  {
    "path": "h-include.js",
    "chars": 8095,
    "preview": "\nconsole.warn('Using h-include.js from the root folder is deprecated, please use lib/h-include.js instead');\n\n// Reflect"
  },
  {
    "path": "lib/h-include-extensions.js",
    "chars": 5251,
    "preview": "/*jslint indent: 2, browser: true, vars: true, nomen: true, loopfunc: true */\n\n// Only loads on refresh(), to be used wi"
  },
  {
    "path": "lib/h-include.js",
    "chars": 7985,
    "preview": "// Reflect.construct polyfill adopted from https://github.com/WebReflection/classtrophobic-es5\n/*! (C) 2017 Andrea Giamm"
  },
  {
    "path": "package.json",
    "chars": 1424,
    "preview": "{\n  \"name\": \"h-include\",\n  \"version\": \"4.5.0\",\n  \"homepage\": \"https://github.com/gustafnk/h-include\",\n  \"repository\": {\n"
  },
  {
    "path": "release-with-deprecation-warning.js",
    "chars": 280,
    "preview": "const fs = require('fs');\nvar prependFile = require('prepend-file');\n\nfs.copyFileSync('./lib/h-include.js', './h-include"
  },
  {
    "path": "static/alt/alt.html",
    "chars": 1179,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n    <title>tes"
  },
  {
    "path": "static/alt/fragment.html",
    "chars": 102,
    "preview": "<span id=\"default-included\" style=\"text-decoration: underline\">default - this text is included</span>\n"
  },
  {
    "path": "static/alt/fragment2.html",
    "chars": 115,
    "preview": "<span id=\"when-false-src-included\" style=\"text-decoration: underline\">when-false-src - this text is included</span>"
  },
  {
    "path": "static/alt/fragment3.html",
    "chars": 93,
    "preview": "<span id=\"alt-included\" style=\"text-decoration: underline\">alt - this text is included</span>"
  },
  {
    "path": "static/alt/fragment4.html",
    "chars": 100,
    "preview": "<span id=\"alt-2-included\" style=\"text-decoration: underline\">alt - this text is also included</span>"
  },
  {
    "path": "static/alt/no-alt.html",
    "chars": 887,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n    <title>tes"
  },
  {
    "path": "static/alt/when-fail-no-when-false-src-alt-error.html",
    "chars": 899,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n    <title>tes"
  },
  {
    "path": "static/alt/when-fail-no-when-false-src-alt-pass.html",
    "chars": 1183,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n    <title>tes"
  },
  {
    "path": "static/alt/when-fail-when-false-src-fail-alt-error.html",
    "chars": 1137,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n    <title>tes"
  },
  {
    "path": "static/alt/when-fail-when-false-src-fail-alt-pass.html",
    "chars": 1209,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n    <title>tes"
  },
  {
    "path": "static/alt/when-pass-no-when-false-src-alt-error.html",
    "chars": 1109,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n    <title>tes"
  },
  {
    "path": "static/alt/when-pass-no-when-false-src-alt-pass.html",
    "chars": 1182,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n    <title>tes"
  },
  {
    "path": "static/alt/when-pass-when-false-src-fail-alt-error.html",
    "chars": 1136,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n    <title>tes"
  },
  {
    "path": "static/alt/when-pass-when-false-src-fail-alt-pass.html",
    "chars": 1208,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n    <title>tes"
  },
  {
    "path": "static/basic/fragment-2.html",
    "chars": 103,
    "preview": "<span id=\"included-2\" style=\"text-decoration: underline\">this text overwrote what was just there</span>"
  },
  {
    "path": "static/basic/fragment.html",
    "chars": 85,
    "preview": "<span id=\"included-1\" style=\"text-decoration: underline\">this text is included</span>"
  },
  {
    "path": "static/basic/index.html",
    "chars": 1619,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n\t<title>h-include T"
  },
  {
    "path": "static/basic-async/fragment-2.html",
    "chars": 103,
    "preview": "<span id=\"included-2\" style=\"text-decoration: underline\">this text overwrote what was just there</span>"
  },
  {
    "path": "static/basic-async/fragment.html",
    "chars": 85,
    "preview": "<span id=\"included-1\" style=\"text-decoration: underline\">this text is included</span>"
  },
  {
    "path": "static/basic-async/index.html",
    "chars": 1588,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n\t<title>h-include T"
  },
  {
    "path": "static/expect.js",
    "chars": 212,
    "preview": "var i = 0;\nwindow.expect = function(passed, actual){\n  console.log('Test', i, 'passed?', passed, !passed ? actual : '');"
  },
  {
    "path": "static/fragment-extraction/full-page.html",
    "chars": 241,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>A page with a fragment</title>\n</head>\n<body>\n\n<h1>A page with a fragment</h1>\n\n<d"
  },
  {
    "path": "static/fragment-extraction/index.html",
    "chars": 694,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n\t<title>h-include T"
  },
  {
    "path": "static/index.html",
    "chars": 1236,
    "preview": "<h1>Links for visual tests</h1>\n\n<ul>\n  <li><a href=\"basic/index.html\">basic</a></li>\n  <li><a href=\"basic-async/index.h"
  },
  {
    "path": "static/lazy-extension/fragment-3.html",
    "chars": 87,
    "preview": "<span id=\"included-3\" style=\"text-decoration: underline\">this text is included 3</span>"
  },
  {
    "path": "static/lazy-extension/fragment.html",
    "chars": 85,
    "preview": "<span id=\"included-1\" style=\"text-decoration: underline\">this text is included</span>"
  },
  {
    "path": "static/lazy-extension/index.html",
    "chars": 4291,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n  <title>h-include"
  },
  {
    "path": "static/media/index.html",
    "chars": 1077,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n\t<title>h-include T"
  },
  {
    "path": "static/media/large.html",
    "chars": 15,
    "preview": "Large viewport\n"
  },
  {
    "path": "static/media/small.html",
    "chars": 15,
    "preview": "Small viewport\n"
  },
  {
    "path": "static/navigate-extension/1.html",
    "chars": 80,
    "preview": "<div id=\"a\"><a href=\"2.html\"><i class=\"link\">Click</i> here <b>now</b></a></div>"
  },
  {
    "path": "static/navigate-extension/2.html",
    "chars": 240,
    "preview": "<div id=\"b\">\n<a href=\"1.html\">Back</a>\n<br><br>\nA box\n<br>\nWith several lines\n<br>\nWith <a href=\"3.html\">another <i clas"
  },
  {
    "path": "static/navigate-extension/3.html",
    "chars": 96,
    "preview": "<div>\n<a href=\"2.html\">Back</a>\n<br><br>\n<div id=\"c\">This is the last box. Goodbye.</div>\n</div>"
  },
  {
    "path": "static/navigate-extension/extract-fragment/1.html",
    "chars": 366,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n  <title>h-include"
  },
  {
    "path": "static/navigate-extension/extract-fragment/2.html",
    "chars": 519,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n  <title>h-include"
  },
  {
    "path": "static/navigate-extension/extract-fragment/3.html",
    "chars": 384,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n  <title>h-include"
  },
  {
    "path": "static/navigate-extension/extract-fragment/index.html",
    "chars": 1185,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n  <title>h-include"
  },
  {
    "path": "static/navigate-extension/index.html",
    "chars": 1064,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n  <title>h-include"
  },
  {
    "path": "static/navigate-extension/nested/1.html",
    "chars": 60,
    "preview": "<div><a href=\"2.html\"><i>Click</i> here <b>now</b></a></div>"
  },
  {
    "path": "static/navigate-extension/nested/2.html",
    "chars": 213,
    "preview": "<div>\n<a href=\"1.html\">Back</a>\n<br><br>\nA box\n<br>\nWith several lines\n<br>\nWith <a href=\"3.html\">another link</a>\n<br>\n"
  },
  {
    "path": "static/navigate-extension/nested/3.html",
    "chars": 78,
    "preview": "<div>\n<a href=\"2.html\">Back</a>\n<br><br>\nThis is the last box. Goodbye.\n</div>"
  },
  {
    "path": "static/navigate-extension/nested/index.html",
    "chars": 1218,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n  <title>h-include"
  },
  {
    "path": "static/navigate-extension/nested/inner.html",
    "chars": 298,
    "preview": "<h2 id=\"h\">Inner container (included)</h2>\n\n<p class=\"box\" id=\"box-1\"><h-include-navigate src=\"1.html\"></h-include-navig"
  },
  {
    "path": "static/none/index.html",
    "chars": 902,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n\t<title>h-include T"
  },
  {
    "path": "static/recursion-not-allowed/index.html",
    "chars": 1075,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n\t<title>h-include T"
  },
  {
    "path": "static/recursion-not-allowed/recursive-fragment.html",
    "chars": 105,
    "preview": "<p>\n  <div class=\"recursive\">Recursive</div>\n  <h-include src=\"recursive-fragment.html\"></h-include>\n</p>"
  },
  {
    "path": "static/style.css",
    "chars": 54,
    "preview": "body {\n  font-family: Helvetica, Arial, sans-serif;\n}\n"
  },
  {
    "path": "static/visual-tests/domparser/body.html",
    "chars": 139,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n</head>\n<body>\n<p>This is a full HTML document which contains HTML, HEAD and BODY tags.</p"
  },
  {
    "path": "static/visual-tests/domparser/domparser.html",
    "chars": 2658,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n<script>this.customElements||document.write('<script src=\"//unpkg.com/document-register-el"
  },
  {
    "path": "static/visual-tests/domparser/main.html",
    "chars": 170,
    "preview": "<!DOCTYPE html>\n<html>\n<body>\n<p>This is a full HTML document which also contains a MAIN tag.</p>\n<main>\n<p>This is the "
  },
  {
    "path": "static/visual-tests/domparser/partial.html",
    "chars": 75,
    "preview": "<p>This is a partial HTML document. It has no HTML, HEAD or BODY tags</p>\n\n"
  },
  {
    "path": "static/visual-tests/import-extension/index.html",
    "chars": 921,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n  <title>h-include"
  },
  {
    "path": "static/visual-tests/import-extension/resource-fragment.html",
    "chars": 264,
    "preview": "<script src=\"/static/import-extension/script-1.js\"></script>\n<link rel=\"stylesheet\" href=\"/static/import-extension/style"
  },
  {
    "path": "static/visual-tests/import-extension/script-1.js",
    "chars": 20,
    "preview": "console.log('Foo');\n"
  },
  {
    "path": "static/visual-tests/import-extension/script-2.js",
    "chars": 20,
    "preview": "console.log('Bar');\n"
  },
  {
    "path": "static/visual-tests/import-extension/styles-1.css",
    "chars": 21,
    "preview": "h1 {\n  color: red;\n}\n"
  },
  {
    "path": "static/visual-tests/import-extension/styles-2.css",
    "chars": 23,
    "preview": "h1 {\n  color: green;\n}\n"
  },
  {
    "path": "static/when/fragment.html",
    "chars": 95,
    "preview": "<span id=\"when-included\" style=\"text-decoration: underline\">when - this text is included</span>"
  },
  {
    "path": "static/when/fragment2.html",
    "chars": 115,
    "preview": "<span id=\"when-false-src-included\" style=\"text-decoration: underline\">when-false-src - this text is included</span>"
  },
  {
    "path": "static/when/when-fail-if-when-false-src.html",
    "chars": 1165,
    "preview": "<!DOCTYPE html>\n<html>\n\n<head>\n  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n  <title>test</ti"
  },
  {
    "path": "static/when/when-fail.html",
    "chars": 1080,
    "preview": "<!DOCTYPE html>\n<html>\n\n<head>\n  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n  <title>test</ti"
  },
  {
    "path": "static/when/when-pass-use-src.html",
    "chars": 1146,
    "preview": "<!DOCTYPE html>\n<html>\n\n<head>\n  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n  <title>test</ti"
  }
]

About this extraction

This page contains the full source code of the gustafnk/h-include GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 79 files (91.3 KB), approximately 26.3k tokens, and a symbol index with 11 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!