pwa-helpers
Advanced tools
Comparing version 0.8.3 to 0.8.4-pre.1
@@ -10,57 +10,32 @@ /** | ||
*/ | ||
/* | ||
This is an [axe-core](https://github.com/dequelabs/axe-core) reporter that returns an | ||
Error containing every a11y violation for an element. Use this if you want to | ||
include `axe-core` in automated Mocha tests, etc. Note that this helper does not | ||
include `axe-core` for you; you must do this separately. | ||
The `axeReport` function takes an optional second argument: | ||
{cleanup: {...}, axeConfig: {...}}, where `cleanup` is a callback to be | ||
called after the test is ran (so that you can remove the element from the DOM, etc) | ||
and `axeConfig` are the optional extra config parameters to pass to axe. | ||
Sample use: | ||
import '../node_modules/axe-core/axe.min.js'; | ||
import { axeReport } from '../node_modules/pwa-helpers/axe-report.js'; | ||
describe('button', function() { | ||
it('is accessible', function() { | ||
const button = document.createElement('button'); | ||
button.textContent = 'click this'; // Test should fail without this line. | ||
return axeReport(button); | ||
// If you need to run any cleanup code after the test is run, you | ||
// can use the `cleanup` object. For example, | ||
// document.body.appendChild(button); | ||
// return axeReport(el, { cleanup() { el.remove(); } }); | ||
}); | ||
}); | ||
*/ | ||
export async function axeReport(dom, config = {}) { | ||
const {cleanup, axeConfig} = config; | ||
const {violations} = await axe.run(dom, axeConfig || { | ||
runOnly: ['wcag2a', 'wcag2aa', 'section508'], | ||
// Ignore tests that are passing. | ||
resultTypes: ['violations'] | ||
}); | ||
if (cleanup) { | ||
await cleanup(); | ||
} | ||
if (!violations.length) { | ||
return; | ||
} | ||
const errorMessage = ['Accessibility Violations', '---']; | ||
for (const violation of violations) { | ||
errorMessage.push(violation.help); | ||
for (const node of violation.nodes) { | ||
errorMessage.push(node.failureSummary); | ||
errorMessage.push(node.html); | ||
const { cleanup, axeConfig } = config; | ||
const defaultConfig = { | ||
runOnly: { | ||
type: 'tag', | ||
values: ['wcag2a', 'wcag2aa', 'section508'] | ||
}, | ||
// Ignore tests that are passing. | ||
resultTypes: ['violations'] | ||
}; | ||
const { violations } = await axe.run(dom, axeConfig || defaultConfig); | ||
if (cleanup) { | ||
await cleanup(); | ||
} | ||
errorMessage.push('---'); | ||
} | ||
throw new Error(errorMessage.join('\n')); | ||
if (!violations.length) { | ||
return; | ||
} | ||
const errorMessage = ['Accessibility Violations', '---']; | ||
for (const violation of violations) { | ||
errorMessage.push(violation.help); | ||
for (const node of violation.nodes) { | ||
if (node.failureSummary) { | ||
errorMessage.push(node.failureSummary); | ||
} | ||
errorMessage.push(node.html); | ||
} | ||
errorMessage.push('---'); | ||
} | ||
throw new Error(errorMessage.join('\n')); | ||
} | ||
//# sourceMappingURL=axe-report.js.map |
@@ -10,41 +10,22 @@ /** | ||
*/ | ||
/* | ||
Mixin for connecting an element to the Redux store; implements the | ||
basic store-connection boilerplate. | ||
Sample use: | ||
import { connect } from '../node_modules/pwa-helpers/connect-mixin.js'; | ||
class MyElement extends connect(store)(HTMLElement) { | ||
// ... | ||
_stateChanged(state) { | ||
this.count = state.data.count; | ||
} | ||
} | ||
*/ | ||
export const connect = (store) => (baseElement) => class extends baseElement { | ||
connectedCallback() { | ||
// Connect the element to the store. | ||
this.__storeUnsubscribe = store.subscribe(() => this._stateChanged(store.getState())); | ||
this._stateChanged(store.getState()); | ||
if (super.connectedCallback) { | ||
super.connectedCallback(); | ||
connectedCallback() { | ||
// Connect the element to the store. | ||
this.__storeUnsubscribe = store.subscribe(() => this._stateChanged(store.getState())); | ||
this._stateChanged(store.getState()); | ||
if (super.connectedCallback) { | ||
super.connectedCallback(); | ||
} | ||
} | ||
} | ||
disconnectedCallback() { | ||
this.__storeUnsubscribe(); | ||
if (super.disconnectedCallback) { | ||
super.disconnectedCallback(); | ||
disconnectedCallback() { | ||
this.__storeUnsubscribe(); | ||
if (super.disconnectedCallback) { | ||
super.disconnectedCallback(); | ||
} | ||
} | ||
} | ||
// This is called every time something is updated in the store. | ||
_stateChanged(state) { | ||
throw new Error('_stateChanged() not implemented', this); | ||
} | ||
// This is called every time something is updated in the store. | ||
_stateChanged(_state) { | ||
throw new Error('_stateChanged() not implemented'); | ||
} | ||
}; | ||
//# sourceMappingURL=connect-mixin.js.map |
@@ -10,16 +10,16 @@ /** | ||
*/ | ||
export const INCREMENT = 'INCREMENT'; | ||
export const DECREMENT = 'DECREMENT'; | ||
; | ||
; | ||
export const increment = () => { | ||
return { | ||
type: INCREMENT | ||
}; | ||
return { | ||
type: INCREMENT | ||
}; | ||
}; | ||
export const decrement = () => { | ||
return { | ||
type: DECREMENT | ||
}; | ||
return { | ||
type: DECREMENT | ||
}; | ||
}; | ||
//# sourceMappingURL=counter.js.map |
@@ -0,1 +1,2 @@ | ||
"use strict"; | ||
/** | ||
@@ -10,3 +11,2 @@ @license | ||
*/ | ||
// For simplicity, we're not using any styles in this element so that we | ||
@@ -21,4 +21,3 @@ // don't have to set up a Shady CSS polyfill. | ||
</p> | ||
` | ||
`; | ||
// This is a reusable element. It is not connected to the store. You can | ||
@@ -28,40 +27,31 @@ // imagine that it could just as well be a third-party element that you | ||
class CounterElement extends HTMLElement { | ||
constructor() { | ||
super(); | ||
// Stamp the template. | ||
let shadowRoot = this.attachShadow({mode: 'open'}); | ||
this.shadowRoot.appendChild(document.importNode(template.content, true)); | ||
shadowRoot.getElementById('plus').addEventListener('click', () => {this._onIncrement()}); | ||
shadowRoot.getElementById('minus').addEventListener('click', () => {this._onDecrement()}); | ||
// Initial values. | ||
this.clicks = 0; // The total number of clicks you've done. | ||
this.value = 0; // The current value of the counter. | ||
this._show(); | ||
} | ||
_onIncrement() { | ||
this.value++; | ||
this.clicks++; | ||
this._show(); | ||
this.dispatchEvent(new CustomEvent('counter-incremented', | ||
{bubbles: false, composed: true})); | ||
} | ||
_onDecrement() { | ||
this.value--; | ||
this.clicks++; | ||
this._show(); | ||
this.dispatchEvent(new CustomEvent('counter-decremented', | ||
{bubbles: false, composed: true})); | ||
} | ||
_show() { | ||
this.shadowRoot.getElementById('clicksSpan').textContent = this.clicks; | ||
this.shadowRoot.getElementById('valueSpan').textContent = this.value; | ||
} | ||
constructor() { | ||
super(); | ||
this.clicks = 0; // The total number of clicks you've done. | ||
this.value = 0; // The current value of the counter. | ||
// Stamp the template. | ||
const shadowRoot = this.attachShadow({ mode: 'open' }); | ||
shadowRoot.appendChild(document.importNode(template.content, true)); | ||
shadowRoot.getElementById('plus').addEventListener('click', () => { this._onIncrement(); }); | ||
shadowRoot.getElementById('minus').addEventListener('click', () => { this._onDecrement(); }); | ||
this._show(); | ||
} | ||
_onIncrement() { | ||
this.value++; | ||
this.clicks++; | ||
this._show(); | ||
this.dispatchEvent(new CustomEvent('counter-incremented', { bubbles: false, composed: true })); | ||
} | ||
_onDecrement() { | ||
this.value--; | ||
this.clicks++; | ||
this._show(); | ||
this.dispatchEvent(new CustomEvent('counter-decremented', { bubbles: false, composed: true })); | ||
} | ||
_show() { | ||
this.shadowRoot.getElementById('clicksSpan').textContent = this.clicks.toString(); | ||
this.shadowRoot.getElementById('valueSpan').textContent = this.value.toString(); | ||
} | ||
} | ||
window.customElements.define('counter-element', CounterElement); | ||
//# sourceMappingURL=counter-element.js.map |
@@ -10,3 +10,2 @@ /** | ||
*/ | ||
import './counter-element.js'; | ||
@@ -16,3 +15,2 @@ import { connect } from '../../connect-mixin.js'; | ||
import { increment, decrement } from '../actions/counter.js'; | ||
/* | ||
@@ -24,3 +22,2 @@ This is an element that is connected to the Redux store, which contains | ||
*/ | ||
// For simplicity, we're not using any styles in this element so that we | ||
@@ -40,43 +37,37 @@ // don't have to set up a Shady CSS polyfill. | ||
</div> | ||
` | ||
`; | ||
class ReduxExample extends connect(store)(HTMLElement) { | ||
constructor() { | ||
super(); | ||
// Stamp the template. | ||
let shadowRoot = this.attachShadow({mode: 'open'}); | ||
this.shadowRoot.appendChild(document.importNode(template.content, true)); | ||
// Cache some elements so that you don't qsa all the time. | ||
this._counter = shadowRoot.querySelector('counter-element'); | ||
this._clicksSpan = shadowRoot.getElementById('clicksSpan'); | ||
this._valueSpan = shadowRoot.getElementById('valueSpan'); | ||
this._didLoadSpan = shadowRoot.getElementById('didLoadSpan'); | ||
// Every time the display of the counter updates, we should save | ||
// these values in the store. | ||
this.addEventListener('counter-incremented', () => store.dispatch(increment())); | ||
this.addEventListener('counter-decremented', () => store.dispatch(decrement())); | ||
shadowRoot.querySelector('button').addEventListener('click', | ||
() => this._loadReducer()); | ||
} | ||
_stateChanged(state) { | ||
// Update the UI. | ||
this._clicksSpan.textContent = this._counter.clicks = state.counter.clicks; | ||
this._valueSpan.textContent = this._counter.value = state.counter.value; | ||
this._didLoadSpan.textContent = state.lazy ? state.lazy.didLoad : 'undefined'; | ||
} | ||
_loadReducer() { | ||
import('../reducers/lazy.js').then((module) => { | ||
const reducer = module.default; | ||
store.addReducers({'lazy': reducer}); | ||
}); | ||
} | ||
constructor() { | ||
super(); | ||
// Stamp the template. | ||
let shadowRoot = this.attachShadow({ mode: 'open' }); | ||
shadowRoot.appendChild(document.importNode(template.content, true)); | ||
// Cache some elements so that you don't qsa all the time. | ||
this._counter = shadowRoot.querySelector('counter-element'); | ||
this._clicksSpan = shadowRoot.getElementById('clicksSpan'); | ||
this._valueSpan = shadowRoot.getElementById('valueSpan'); | ||
this._didLoadSpan = shadowRoot.getElementById('didLoadSpan'); | ||
// Every time the display of the counter updates, we should save | ||
// these values in the store. | ||
this.addEventListener('counter-incremented', () => store.dispatch(increment())); | ||
this.addEventListener('counter-decremented', () => store.dispatch(decrement())); | ||
shadowRoot.querySelector('button').addEventListener('click', () => this._loadReducer()); | ||
} | ||
_stateChanged(state) { | ||
const numClicks = this._counter.clicks = state.counter.clicks; | ||
const value = this._counter.value = state.counter.value; | ||
// Update the UI. | ||
this._clicksSpan.textContent = numClicks.toString(); | ||
this._valueSpan.textContent = value.toString(); | ||
this._didLoadSpan.textContent = state.lazy ? state.lazy.didLoad.toString() : 'undefined'; | ||
} | ||
_loadReducer() { | ||
import('../reducers/lazy.js').then((module) => { | ||
const reducer = module.default; | ||
const reducerMap = { 'lazy': reducer }; | ||
store.addReducers(reducerMap); | ||
}); | ||
} | ||
} | ||
window.customElements.define('redux-example', ReduxExample); | ||
//# sourceMappingURL=redux-example.js.map |
@@ -10,24 +10,14 @@ /** | ||
*/ | ||
import { INCREMENT, DECREMENT } from '../actions/counter.js'; | ||
const app = (state = {clicks: 0, value: 0}, action) => { | ||
switch (action.type) { | ||
case INCREMENT: | ||
return { | ||
...state, | ||
clicks: state.clicks + 1, | ||
value: state.value + 1 | ||
} | ||
case DECREMENT: | ||
return { | ||
...state, | ||
clicks: state.clicks + 1, | ||
value: state.value - 1 | ||
} | ||
default: | ||
return state; | ||
} | ||
} | ||
const app = (state = { clicks: 0, value: 0 }, action) => { | ||
switch (action.type) { | ||
case INCREMENT: | ||
return Object.assign({}, state, { clicks: state.clicks + 1, value: state.value + 1 }); | ||
case DECREMENT: | ||
return Object.assign({}, state, { clicks: state.clicks + 1, value: state.value - 1 }); | ||
default: | ||
return state; | ||
} | ||
}; | ||
export default app; | ||
//# sourceMappingURL=counter.js.map |
@@ -10,8 +10,7 @@ /** | ||
*/ | ||
// This reducer doesn't do anything other than boot up. | ||
const lazy = (state = {didLoad:true}, action) => { | ||
return state; | ||
} | ||
const lazy = (state = { didLoad: true }) => { | ||
return state; | ||
}; | ||
export default lazy; | ||
//# sourceMappingURL=lazy.js.map |
@@ -10,28 +10,15 @@ /** | ||
*/ | ||
// Redux assumes `process.env.NODE_ENV` exists in the ES module build. | ||
// https://github.com/reactjs/redux/issues/2907 | ||
window.process = { env: { NODE_ENV: 'production' } }; | ||
import createStore from 'https://unpkg.com/redux@3.7.2/es/createStore?module'; | ||
import combineReducers from 'https://unpkg.com/redux@3.7.2/es/combineReducers?module'; | ||
import origCompose from 'https://unpkg.com/redux@3.7.2/es/compose?module'; | ||
import { lazyReducerEnhancer } from '../lazy-reducer-enhancer.js' | ||
import { combineReducers, compose, createStore } from 'redux'; | ||
import { lazyReducerEnhancer } from '../lazy-reducer-enhancer.js'; | ||
// Initially loaded reducers. | ||
import counter from './reducers/counter.js'; | ||
// Sets up a Chrome extension for time travel debugging. | ||
// See https://github.com/zalmoxisus/redux-devtools-extension for more information. | ||
const compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || origCompose; | ||
const devCompose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; | ||
// Initializes the Redux store with a lazyReducerEnhancer (so that you can | ||
// lazily add reducers after the store has been created). | ||
export const store = createStore( | ||
(state, action) => state, | ||
compose(lazyReducerEnhancer(combineReducers)) | ||
); | ||
// Initially loaded reducers. | ||
import counter from './reducers/counter.js'; | ||
export const store = createStore(state => state, devCompose(lazyReducerEnhancer(combineReducers))); | ||
store.addReducers({ | ||
counter | ||
counter | ||
}); | ||
//# sourceMappingURL=store.js.map |
@@ -10,37 +10,15 @@ /** | ||
*/ | ||
/* | ||
If you are lazy loading any connected elements, then these elements must be | ||
able to lazily install their reducers. This is a store enhancer that | ||
enables that. | ||
Sample use (where you define your redux store, in store.js): | ||
import lazyReducerEnhancer from '../node_modules/pwa-helpers/lazy-reducer-enhancer.js'; | ||
import someReducer from './reducers/someReducer.js'; | ||
export const store = createStore( | ||
(state, action) => state, | ||
compose(lazyReducerEnhancer(combineReducers), applyMiddleware(thunk)) | ||
); | ||
Then, in your page/element, you can lazy load a specific reducer with: | ||
store.addReducers({ | ||
someReducer | ||
}); | ||
*/ | ||
export const lazyReducerEnhancer = function(combineReducers) { | ||
return (nextCreator) => { | ||
return (origReducer, preloadedState) => { | ||
let lazyReducers = {}; | ||
const nextStore = nextCreator(origReducer, preloadedState) | ||
function addReducers(newReducers) { | ||
this.replaceReducer(combineReducers(lazyReducers = | ||
Object.assign({}, lazyReducers, newReducers) | ||
)); | ||
}; | ||
return Object.assign({}, nextStore, {addReducers}); | ||
} | ||
} | ||
} | ||
export const lazyReducerEnhancer = (combineReducers) => { | ||
const enhancer = (nextCreator) => { | ||
return (origReducer, preloadedState) => { | ||
let lazyReducers = {}; | ||
const nextStore = nextCreator(origReducer, preloadedState); | ||
return Object.assign({}, nextStore, { addReducers(newReducers) { | ||
const combinedReducerMap = Object.assign({}, lazyReducers, newReducers); | ||
this.replaceReducer(combineReducers(lazyReducers = combinedReducerMap)); | ||
} }); | ||
}; | ||
}; | ||
return enhancer; | ||
}; | ||
//# sourceMappingURL=lazy-reducer-enhancer.js.map |
@@ -10,3 +10,2 @@ /** | ||
*/ | ||
/* | ||
@@ -27,7 +26,7 @@ Utility method that calls a callback whenever a media-query matches in response | ||
*/ | ||
export const installMediaQueryWatcher = (mediaQuery, layoutChangedCallback) => { | ||
let mql = window.matchMedia(mediaQuery); | ||
mql.addListener((e) => layoutChangedCallback(e.matches)); | ||
layoutChangedCallback(mql.matches); | ||
let mql = window.matchMedia(mediaQuery); | ||
mql.addListener((e) => layoutChangedCallback(e.matches)); | ||
layoutChangedCallback(mql.matches); | ||
}; | ||
//# sourceMappingURL=media-query.js.map |
@@ -10,3 +10,2 @@ /** | ||
*/ | ||
/* | ||
@@ -32,34 +31,30 @@ Utility method that updates the page's open graph and Twitter card metadata. | ||
*/ | ||
export const updateMetadata = ({title, description, url, image}) => { | ||
if (title) { | ||
document.title = title; | ||
_setMeta('property', 'og:title', document.title); | ||
_setMeta('property', 'twitter:title', document.title); | ||
} | ||
if (description) { | ||
_setMeta('name', 'description', description); | ||
_setMeta('property', 'og:description', description); | ||
_setMeta('property', 'twitter:description', description); | ||
} | ||
if (image) { | ||
_setMeta('property', 'og:image', image); | ||
_setMeta('property', 'twitter:image:src', image); | ||
} | ||
url = url || document.location.href; | ||
_setMeta('property', 'og:url', url); | ||
_setMeta('property', 'twitter:url', url); | ||
} | ||
export const updateMetadata = ({ title, description, url, image }) => { | ||
if (title) { | ||
document.title = title; | ||
_setMeta('property', 'og:title', document.title); | ||
_setMeta('property', 'twitter:title', document.title); | ||
} | ||
if (description) { | ||
_setMeta('name', 'description', description); | ||
_setMeta('property', 'og:description', description); | ||
_setMeta('property', 'twitter:description', description); | ||
} | ||
if (image) { | ||
_setMeta('property', 'og:image', image); | ||
_setMeta('property', 'twitter:image:src', image); | ||
} | ||
url = url || document.location.href; | ||
_setMeta('property', 'og:url', url); | ||
_setMeta('property', 'twitter:url', url); | ||
}; | ||
function _setMeta(attrName, attrValue, content) { | ||
let element = document.head.querySelector(`meta[${attrName}="${attrValue}"]`); | ||
if (!element) { | ||
element = document.createElement('meta'); | ||
element.setAttribute(attrName, attrValue); | ||
document.head.appendChild(element); | ||
} | ||
element.setAttribute('content', content || ''); | ||
let element = document.head.querySelector(`meta[${attrName}="${attrValue}"]`); | ||
if (!element) { | ||
element = document.createElement('meta'); | ||
element.setAttribute(attrName, attrValue); | ||
document.head.appendChild(element); | ||
} | ||
element.setAttribute('content', content || ''); | ||
} | ||
//# sourceMappingURL=metadata.js.map |
@@ -10,3 +10,2 @@ /** | ||
*/ | ||
/* | ||
@@ -25,8 +24,7 @@ Utility method that calls a callback whenever the network connectivity of the app changes. | ||
*/ | ||
export const installOfflineWatcher = (offlineUpdatedCallback) => { | ||
window.addEventListener('online', () => offlineUpdatedCallback(false)); | ||
window.addEventListener('offline', () => offlineUpdatedCallback(true)); | ||
offlineUpdatedCallback(navigator.onLine === false); | ||
window.addEventListener('online', () => offlineUpdatedCallback(false)); | ||
window.addEventListener('offline', () => offlineUpdatedCallback(true)); | ||
offlineUpdatedCallback(navigator.onLine === false); | ||
}; | ||
//# sourceMappingURL=network.js.map |
{ | ||
"name": "pwa-helpers", | ||
"version": "0.8.3", | ||
"version": "0.8.4-pre.1", | ||
"description": "Small helper methods or mixins to help you build web apps.", | ||
@@ -15,3 +15,7 @@ "contributors": [ | ||
"module": "pwa-helpers.js", | ||
"devDependencies": {}, | ||
"devDependencies": { | ||
"axe-core": "^3.0.2", | ||
"redux": "^4.0.0", | ||
"typescript": "^3.0.3" | ||
}, | ||
"bugs": { | ||
@@ -22,5 +26,6 @@ "url": "https://github.com/polymer/pwa-helpers/issues" | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"test": "echo \"Error: no test specified\" && exit 1", | ||
"build": "tsc" | ||
}, | ||
"author": "The Polymer Authors" | ||
} |
@@ -10,3 +10,2 @@ /** | ||
*/ | ||
export { connect } from './connect-mixin.js'; | ||
@@ -18,1 +17,2 @@ export { lazyReducerEnhancer } from './lazy-reducer-enhancer.js'; | ||
export { installRouter } from './router.js'; | ||
//# sourceMappingURL=pwa-helpers.js.map |
@@ -10,3 +10,2 @@ /** | ||
*/ | ||
/* | ||
@@ -48,29 +47,28 @@ Basic router that calls a callback whenever the location is updated. | ||
*/ | ||
export const installRouter = (locationUpdatedCallback) => { | ||
document.body.addEventListener('click', e => { | ||
if (e.defaultPrevented || e.button !== 0 || | ||
e.metaKey || e.ctrlKey || e.shiftKey) return; | ||
const anchor = e.composedPath().filter(n => n.tagName === 'A')[0]; | ||
if (!anchor || anchor.target || | ||
anchor.hasAttribute('download') || | ||
anchor.getAttribute('rel') === 'external') return; | ||
const href = anchor.href; | ||
if (!href || href.indexOf('mailto:') !== -1) return; | ||
const location = window.location; | ||
const origin = location.origin || location.protocol + '//' + location.host; | ||
if (href.indexOf(origin) !== 0) return; | ||
e.preventDefault(); | ||
if (href !== location.href) { | ||
window.history.pushState({}, '', href); | ||
locationUpdatedCallback(location, e); | ||
} | ||
}); | ||
window.addEventListener('popstate', e => locationUpdatedCallback(window.location, e)); | ||
locationUpdatedCallback(window.location, null /* event */); | ||
document.body.addEventListener('click', e => { | ||
if (e.defaultPrevented || e.button !== 0 || | ||
e.metaKey || e.ctrlKey || e.shiftKey) | ||
return; | ||
const anchor = e.composedPath().filter(n => n.tagName === 'A')[0]; | ||
if (!anchor || anchor.target || | ||
anchor.hasAttribute('download') || | ||
anchor.getAttribute('rel') === 'external') | ||
return; | ||
const href = anchor.href; | ||
if (!href || href.indexOf('mailto:') !== -1) | ||
return; | ||
const location = window.location; | ||
const origin = location.origin || location.protocol + '//' + location.host; | ||
if (href.indexOf(origin) !== 0) | ||
return; | ||
e.preventDefault(); | ||
if (href !== location.href) { | ||
window.history.pushState({}, '', href); | ||
locationUpdatedCallback(location, e); | ||
} | ||
}); | ||
window.addEventListener('popstate', e => locationUpdatedCallback(window.location, e)); | ||
locationUpdatedCallback(window.location, null /* event */); | ||
}; | ||
//# sourceMappingURL=router.js.map |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 3 instances in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
179357
71
2092
2
3