Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@github/include-fragment-element

Package Overview
Dependencies
Maintainers
20
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@github/include-fragment-element - npm Package Compare versions

Comparing version 6.0.1 to 6.1.0

8

dist/index.d.ts

@@ -0,3 +1,10 @@

interface CSPTrustedTypesPolicy {
createHTML: (s: string, response: Response) => CSPTrustedHTMLToStringable;
}
interface CSPTrustedHTMLToStringable {
toString: () => string;
}
export default class IncludeFragmentElement extends HTMLElement {
#private;
static setCSPTrustedTypesPolicy(policy: CSPTrustedTypesPolicy | Promise<CSPTrustedTypesPolicy> | null): void;
static get observedAttributes(): string[];

@@ -26,1 +33,2 @@ get src(): string;

}
export {};

137

dist/index.js

@@ -12,38 +12,11 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {

};
var _IncludeFragmentElement_instances, _IncludeFragmentElement_busy, _IncludeFragmentElement_observer, _IncludeFragmentElement_handleData, _IncludeFragmentElement_getData, _IncludeFragmentElement_fetchDataWithEvents;
var _IncludeFragmentElement_instances, _IncludeFragmentElement_busy, _IncludeFragmentElement_observer, _IncludeFragmentElement_handleData, _IncludeFragmentElement_getData, _IncludeFragmentElement_getStringOrErrorData, _IncludeFragmentElement_task, _IncludeFragmentElement_fetchDataWithEvents;
const privateData = new WeakMap();
function task() {
return new Promise(resolve => setTimeout(resolve, 0));
}
function isWildcard(accept) {
return accept && !!accept.split(',').find(x => x.match(/^\s*\*\/\*/));
}
let cspTrustedTypesPolicyPromise = null;
export default class IncludeFragmentElement extends HTMLElement {
constructor() {
super();
_IncludeFragmentElement_instances.add(this);
_IncludeFragmentElement_busy.set(this, false);
_IncludeFragmentElement_observer.set(this, new IntersectionObserver(entries => {
for (const entry of entries) {
if (entry.isIntersecting) {
const { target } = entry;
__classPrivateFieldGet(this, _IncludeFragmentElement_observer, "f").unobserve(target);
if (!(target instanceof IncludeFragmentElement))
return;
if (target.loading === 'lazy') {
__classPrivateFieldGet(this, _IncludeFragmentElement_instances, "m", _IncludeFragmentElement_handleData).call(this);
}
}
}
}, {
rootMargin: '0px 0px 256px 0px',
threshold: 0.01
}));
this.attachShadow({ mode: 'open' }).innerHTML = `
<style>
:host {
display: block;
}
</style>
<slot></slot>`;
static setCSPTrustedTypesPolicy(policy) {
cspTrustedTypesPolicyPromise = policy === null ? policy : Promise.resolve(policy);
}

@@ -82,3 +55,3 @@ static get observedAttributes() {

get data() {
return __classPrivateFieldGet(this, _IncludeFragmentElement_instances, "m", _IncludeFragmentElement_getData).call(this);
return __classPrivateFieldGet(this, _IncludeFragmentElement_instances, "m", _IncludeFragmentElement_getStringOrErrorData).call(this);
}

@@ -97,2 +70,27 @@ attributeChangedCallback(attribute, oldVal) {

}
constructor() {
super();
_IncludeFragmentElement_instances.add(this);
_IncludeFragmentElement_busy.set(this, false);
_IncludeFragmentElement_observer.set(this, new IntersectionObserver(entries => {
for (const entry of entries) {
if (entry.isIntersecting) {
const { target } = entry;
__classPrivateFieldGet(this, _IncludeFragmentElement_observer, "f").unobserve(target);
if (!(target instanceof IncludeFragmentElement))
return;
if (target.loading === 'lazy') {
__classPrivateFieldGet(this, _IncludeFragmentElement_instances, "m", _IncludeFragmentElement_handleData).call(this);
}
}
}
}, {
rootMargin: '0px 0px 256px 0px',
threshold: 0.01
}));
const shadowRoot = this.attachShadow({ mode: 'open' });
const style = document.createElement('style');
style.textContent = `:host {display: block;}`;
shadowRoot.append(style, document.createElement('slot'));
}
connectedCallback() {

@@ -120,3 +118,3 @@ if (this.src && this.loading === 'eager') {

load() {
return __classPrivateFieldGet(this, _IncludeFragmentElement_instances, "m", _IncludeFragmentElement_getData).call(this);
return __classPrivateFieldGet(this, _IncludeFragmentElement_instances, "m", _IncludeFragmentElement_getStringOrErrorData).call(this);
}

@@ -127,10 +125,15 @@ fetch(request) {

}
_IncludeFragmentElement_busy = new WeakMap(), _IncludeFragmentElement_observer = new WeakMap(), _IncludeFragmentElement_instances = new WeakSet(), _IncludeFragmentElement_handleData = function _IncludeFragmentElement_handleData() {
_IncludeFragmentElement_busy = new WeakMap(), _IncludeFragmentElement_observer = new WeakMap(), _IncludeFragmentElement_instances = new WeakSet(), _IncludeFragmentElement_handleData = async function _IncludeFragmentElement_handleData() {
if (__classPrivateFieldGet(this, _IncludeFragmentElement_busy, "f"))
return Promise.resolve();
return;
__classPrivateFieldSet(this, _IncludeFragmentElement_busy, true, "f");
__classPrivateFieldGet(this, _IncludeFragmentElement_observer, "f").unobserve(this);
return __classPrivateFieldGet(this, _IncludeFragmentElement_instances, "m", _IncludeFragmentElement_getData).call(this).then((html) => {
try {
const data = await __classPrivateFieldGet(this, _IncludeFragmentElement_instances, "m", _IncludeFragmentElement_getData).call(this);
if (data instanceof Error) {
throw data;
}
const dataTreatedAsString = data;
const template = document.createElement('template');
template.innerHTML = html;
template.innerHTML = dataTreatedAsString;
const fragment = document.importNode(template.content, true);

@@ -142,12 +145,14 @@ const canceled = !this.dispatchEvent(new CustomEvent('include-fragment-replace', { cancelable: true, detail: { fragment } }));

this.dispatchEvent(new CustomEvent('include-fragment-replaced'));
}, () => {
}
catch (_a) {
this.classList.add('is-error');
});
}, _IncludeFragmentElement_getData = function _IncludeFragmentElement_getData() {
}
}, _IncludeFragmentElement_getData = async function _IncludeFragmentElement_getData() {
const src = this.src;
let data = privateData.get(this);
if (data && data.src === src) {
return data.data;
const cachedData = privateData.get(this);
if (cachedData && cachedData.src === src) {
return cachedData.data;
}
else {
let data;
if (src) {

@@ -162,9 +167,17 @@ data = __classPrivateFieldGet(this, _IncludeFragmentElement_instances, "m", _IncludeFragmentElement_fetchDataWithEvents).call(this);

}
}, _IncludeFragmentElement_fetchDataWithEvents = function _IncludeFragmentElement_fetchDataWithEvents() {
return task()
.then(() => {
this.dispatchEvent(new Event('loadstart'));
return this.fetch(this.request());
})
.then(response => {
}, _IncludeFragmentElement_getStringOrErrorData = async function _IncludeFragmentElement_getStringOrErrorData() {
const data = await __classPrivateFieldGet(this, _IncludeFragmentElement_instances, "m", _IncludeFragmentElement_getData).call(this);
if (data instanceof Error) {
throw data;
}
return data.toString();
}, _IncludeFragmentElement_task = async function _IncludeFragmentElement_task(eventsToDispatch) {
await new Promise(resolve => setTimeout(resolve, 0));
for (const eventType of eventsToDispatch) {
this.dispatchEvent(new Event(eventType));
}
}, _IncludeFragmentElement_fetchDataWithEvents = async function _IncludeFragmentElement_fetchDataWithEvents() {
try {
await __classPrivateFieldGet(this, _IncludeFragmentElement_instances, "m", _IncludeFragmentElement_task).call(this, ['loadstart']);
const response = await this.fetch(this.request());
if (response.status !== 200) {

@@ -177,17 +190,15 @@ throw new Error(`Failed to load resource: the server responded with a status of ${response.status}`);

}
return response.text();
})
.then(data => {
task().then(() => {
this.dispatchEvent(new Event('load'));
this.dispatchEvent(new Event('loadend'));
});
const responseText = await response.text();
let data = responseText;
if (cspTrustedTypesPolicyPromise) {
const cspTrustedTypesPolicy = await cspTrustedTypesPolicyPromise;
data = cspTrustedTypesPolicy.createHTML(responseText, response);
}
__classPrivateFieldGet(this, _IncludeFragmentElement_instances, "m", _IncludeFragmentElement_task).call(this, ['load', 'loadend']);
return data;
}, error => {
task().then(() => {
this.dispatchEvent(new Event('error'));
this.dispatchEvent(new Event('loadend'));
});
}
catch (error) {
__classPrivateFieldGet(this, _IncludeFragmentElement_instances, "m", _IncludeFragmentElement_task).call(this, ['error', 'loadend']);
throw error;
});
}
};

@@ -194,0 +205,0 @@ if (!window.customElements.get('include-fragment')) {

{
"name": "@github/include-fragment-element",
"version": "6.0.1",
"version": "6.1.0",
"main": "dist/index.js",

@@ -16,6 +16,7 @@ "module": "dist/index.js",

"lint": "eslint . --ext .js,.ts && tsc --noEmit",
"format": "eslint --fix . --ext .js,.ts",
"prebuild": "npm run clean && npm run lint && mkdir dist",
"build": "tsc",
"pretest": "npm run build",
"test": "karma start ./test/karma.config.cjs",
"test": "web-test-runner",
"prepublishOnly": "npm run build",

@@ -27,12 +28,9 @@ "postpublish": "npm publish --ignore-scripts --@github:registry='https://npm.pkg.github.com'"

"@github/prettier-config": "0.0.4",
"chai": "^4.3.4",
"chromium": "^3.0.3",
"@open-wc/testing": "^3.1.7",
"@web/dev-server-esbuild": "^0.3.3",
"@web/test-runner": "^0.15.0",
"@web/test-runner-playwright": "^0.9.0",
"esbuild": "^0.15.15",
"eslint": "^8.12.0",
"eslint-plugin-github": "^4.3.6",
"karma": "^6.3.4",
"karma-chai": "^0.1.0",
"karma-chrome-launcher": "^3.1.0",
"karma-mocha": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
"mocha": "^9.0.3",
"typescript": "^4.3.5"

@@ -39,0 +37,0 @@ },

@@ -103,3 +103,48 @@ # &lt;include-fragment&gt; element

### CSP Trusted Types
You can call `setCSPTrustedTypesPolicy(policy: TrustedTypePolicy | Promise<TrustedTypePolicy> | null)` from JavaScript to set a [CSP trusted types policy](https://web.dev/trusted-types/), which can perform (synchronous) filtering or rejection of the `fetch` response before it is inserted into the page:
```ts
import IncludeFragmentElement from "include-fragment-element";
import DOMPurify from "dompurify"; // Using https://github.com/cure53/DOMPurify
// This policy removes all HTML markup except links.
const policy = trustedTypes.createPolicy("links-only", {
createHTML: (htmlText: string) => {
return DOMPurify.sanitize(htmlText, {
ALLOWED_TAGS: ["a"],
ALLOWED_ATTR: ["href"],
RETURN_TRUSTED_TYPE: true,
});
},
});
IncludeFragmentElement.setCSPTrustedTypesPolicy(policy);
```
The policy has access to the `fetch` response object. Due to platform constraints, only synchronous information from the response (in addition to the HTML text body) can be used in the policy:
```ts
import IncludeFragmentElement from "include-fragment-element";
const policy = trustedTypes.createPolicy("require-server-header", {
createHTML: (htmlText: string, response: Response) => {
if (response.headers.get("X-Server-Sanitized") !== "sanitized=true") {
// Note: this will reject the contents, but the error may be caught before it shows in the JS console.
throw new Error("Rejecting HTML that was not marked by the server as sanitized.");
}
return htmlText;
},
});
IncludeFragmentElement.setCSPTrustedTypesPolicy(policy);
```
Note that:
- Only a single policy can be set, shared by all `IncludeFragmentElement` fetches.
- You should call `setCSPTrustedTypesPolicy()` ahead of any other load of `include-fragment-element` in your code.
- If your policy itself requires asynchronous work to construct, you can also pass a `Promise<TrustedTypePolicy>`.
- Pass `null` to remove the policy.
- Not all browsers [support the trusted types API in JavaScript](https://caniuse.com/mdn-api_trustedtypes). You may want to use the [recommended tinyfill](https://github.com/w3c/trusted-types#tinyfill) to construct a policy without causing issues in other browsers.
## Relation to Server Side Includes

@@ -106,0 +151,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc