## License
The project is developed under the **MIT** license:
- **Permissions**: This software and derivatives may be used for commercial purposes, you may distribute this software, this software may be modified and you may use and modify the software without distributing it.
- **Conditions**: Include a copy of the license and copyright notice with the code.
- **Limitations**: Software is provided without warranty and the software author/license owner cannot be held liable for damages.
Read the [full license](LICENSE.md) for more information about your rights.
================================================
FILE: TODO.md
================================================
# Todos
- [x][m] Router : allow leading slash ?
- [x][m] Reload current page
- [x][m] Prevent `xlink:href` on link enter (eg: SVG)
- [x][s] No transitions ? weird behavior…
- [ ][w] BS, how to fix it (definitely)
- [ ][m] (npm)ignore .DS_Store files
---
- [ ] @barba/
- [ ] **transitions** (basic, ready-to-use. e.g.: fade, slide, …)
- [ ] **css** (add CSS classes via hooks)
- [ ] **loader** ??? (programatically fetch and cache pages - also see [quicklink](https://github.com/GoogleChromeLabs/quicklink))
- [ ] Tests:
- [ ] unit tests
- [ ] e2e tests (puppetteer? / cypress?)
- [ ] Documentation
- [ ] Manual (instructions, examples, …)
- [ ] Auto generated from code
- [ ] Builds / releases
- [ ] auto-update version(s)
- [ ] auto-update changelogs
- [ ] auto-update file gzip size (website and readme)
- [ ] CI (tests, coverage on push, PR, …)
- [ ] Force git commit to follow a certain schema
- [ ] License (find correct open source license)
- > Luigi said: anyone can do what they want, but:
>
> - they can't resell it as it is
> - I have the right in any moment to not allow a specific use
- NB: This seems conflicting with open source core principles
Following are the most "restrictive" :)
- [GNU AGPLv3](https://choosealicense.com/licenses/agpl-3.0/)
- [Open Software License 3.0](https://choosealicense.com/licenses/osl-3.0/)
- [European Union Public License 1.2](https://choosealicense.com/licenses/eupl-1.2/)
- [ ] Community
- [x] Github issue template
- [x] Forum / chat -> [Slack](https://barbajs.slack.com)
- [ ] Other
- [ ] Make jest work with `babel.config.js` (global + optional local merge)
- https://github.com/babel/babel/issues/7208
- https://github.com/facebook/jest/issues/6053#issuecomment-383632515
- https://babeljs.io/docs/en/options
- https://babeljs.io/docs/en/config-files
- ```
@barba/core: import barba from '../src';
@barba/core: ^^^^^
@barba/core: SyntaxError: Unexpected identifier
@barba/core: at ScriptTransformer._transformAndBuildScript (../../node_modules/jest-runtime/build/script_transformer.js:403:17)
@barba/core: babel.config.js:root
@barba/core: .babelrc.js:core
```
- [ ] Repo transfer?
- [doc](https://help.github.com/articles/transferring-a-repository/)
- [hack post](https://francisco.io/blog/transferring-github-stars/)
- VSCode extensions recommendations? settings?
================================================
FILE: commitlint.config.js
================================================
module.exports = {
extends: ['ccgls'],
};
================================================
FILE: cypress/fixtures/example.json
================================================
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}
================================================
FILE: cypress/plugins/index.js
================================================
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/* eslint-disable consistent-return, no-unused-vars */
module.exports = (on, config) => {
// https://github.com/cypress-io/cypress/issues/1872#issuecomment-450807452
on('before:browser:launch', (browser = {}, args) => {
if (browser.name === 'chrome') {
// ^ make sure this is your browser name, you may
// be using 'canary' or 'chromium' for example, so change it to match!
args.push('--proxy-bypass-list=<-loopback>');
return args;
}
});
};
/* eslint-enable consistent-return, no-unused-vars */
================================================
FILE: cypress/support/commands.js
================================================
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
// Automatically prepend "root path" depending on package
// TODO: it breaks "run all"
Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
const r = /^packages\/([a-z]*)\/(__e2e__)\/.*\.spec.js$/;
const root = Cypress.spec.relative.replace(r, '$1/__web__');
originalFn(root + url, options);
});
Cypress.Commands.add('prepare', (url, title, namespace) => {
// 1. Go to home
cy.visit(url);
// 2. Should have wrapper and container
cy.get('[data-barba=wrapper]')
.as('wrapper')
.should('exist');
cy.get('[data-barba=container]').should('exist');
// 3. Titles have correct content
cy.title().should('contain', title);
cy.get('[data-test=title]')
.as('h1') // Alias to @h1
.should('contain', title);
// 4. Aliases current container
cy.get('[data-test-container=current]').as('current');
// 4. Check namespace if provided
if (namespace) {
cy.get('@current').should('have.attr', 'data-barba-namespace', namespace);
}
});
Cypress.Commands.add('final', (url, title, namespace) => {
// 0. Wrapper is the same
cy.get('@wrapper').should('have.attr', 'data-test-wrapper', 'current');
// 1. URL has changed
cy.url().should('include', url);
// 2. H1 has changed
cy.get('@h1').should('contain', title);
// 3. Page title has changed
cy.title().should('contain', title);
// 4. Current container has been removed
cy.get('@current').should('not.exist');
// 5. Next container exists
cy.get('[data-test-container=next]')
.as('next')
.should('exist');
// 6. Check namespace if provided
if (namespace) {
cy.get('@next').should('have.attr', 'data-barba-namespace', namespace);
}
});
================================================
FILE: cypress/support/e2e.js
================================================
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands';
// Alternatively you can use CommonJS syntax:
// require('./commands')
================================================
FILE: cypress.config.ts
================================================
import { defineConfig } from 'cypress'
export default defineConfig({
fixturesFolder: './cypress/fixtures',
screenshotsFolder: './cypress/screenshots',
videosFolder: './cypress/videos',
projectId: 'ngfcig',
e2e: {
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
setupNodeEvents(on, config) {
return require('./cypress/plugins/index.js')(on, config)
},
baseUrl: 'http://localhost:8111/packages/',
specPattern: './packages/**/__e2e__/**/*.spec.js',
},
})
================================================
FILE: documentation/theme/assets/css/override.css
================================================
.tsd-signature-symbol {
hyphens: auto;
}
/* Hack: hide layout instructions */
.tsd-panel > hr:first-child,
.tsd-panel > hr + p,
.tsd-panel > hr + p + hr {
display: none;
}
blockquote {
border-left: 4px solid #e0e2e5;
margin-left: 0;
padding-left: 20px;
color: #69737d;
}
================================================
FILE: documentation/theme/layouts/default.hbs
================================================
{{#ifCond model.name '==' project.name}}{{project.name}}{{else}}{{model.name}} | {{project.name}}{{/ifCond}}
{{> header}}
{{{contents}}}
{{> footer}}
{{> analytics}}
================================================
FILE: jest.config.js
================================================
module.exports = {
collectCoverageFrom: [
'packages/**/src/**/*.ts',
'!packages/**/src/**/*.d.ts',
'!packages/**/src/typings.ts',
'!packages/**/src/**/index.ts',
'!packages/**/src/polyfills/**.ts',
'!packages/core/src/utils/helpers.ts',
],
coverageThreshold: {
global: {
statements: 95,
branches: 95,
functions: 95,
lines: 95,
},
},
preset: 'ts-jest',
resetMocks: true,
testEnvironment: 'jest-environment-jsdom-global',
testMatch: ['**/__tests__/**/*.test.ts'],
transformIgnorePatterns: ['.*(node_modules)(?!.*@barba.*).*$'],
verbose: true,
watchPlugins: ['jest-watch-lerna-packages'],
};
================================================
FILE: lerna.json
================================================
{
"command": {
"publish": {
"conventionalCommits": true,
"message": "chore(release): 🔖 publish",
"npmClient": "npm"
},
"version": {
"allowBranch": "main"
}
},
"npmClient": "yarn",
"packages": [
"packages/*"
],
"version": "independent",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
================================================
FILE: package.json
================================================
{
"name": "root",
"private": true,
"devDependencies": {
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@commitlint/config-lerna-scopes": "^19.0.0",
"@types/jest": "24.9.1",
"@types/lodash": "^4.17.7",
"all-contributors-cli": "^6.26.1",
"babel-eslint": "^10.1.0",
"commitizen": "^4.3.0",
"commitlint-config-ccgls": "1.4.8",
"coveralls": "^3.1.1",
"cypress": "^13.13.2",
"cz-ccgls": "^0.4.6",
"eslint": "^8.57.0",
"eslint-plugin-cypress": "^2.15.2",
"gzip-size": "^7.0.0",
"http-server": "14.1.1",
"husky": "^9.1.4",
"jest": "26.3.0",
"jest-environment-jsdom-global": "^4.0.0",
"jest-watch-lerna-packages": "^1.1.0",
"lerna": "^8.1.7",
"lint-staged": "15.2.7",
"lodash": "^4.17.11",
"microbundle": "0.15.1",
"npm-run-all": "4.1.5",
"prettier": "^3.3.3",
"rimraf": "6.0.1",
"source-map-explorer": "2.5.3",
"start-server-and-test": "^1.15.5",
"ts-jest": "26.3.0",
"tslint": "^6.1.3",
"typedoc": "0.15.8",
"typedoc-plugin-external-module-name": "^4.0.6",
"typedoc-plugin-sourcefile-url": "^1.0.6",
"typescript": "^4.9.5",
"typescript-tslint-plugin": "1.0.2",
"wait-for-expect": "3.0.2",
"xhr-mock": "^2.4.1"
},
"license": "MIT",
"workspaces": [
"packages/*"
],
"types": "typings",
"scripts": {
"prepare": "husky",
"build": "lerna run build",
"build:watch": "lerna run build:watch --parallel",
"clean": "rimraf docs && lerna clean",
"clear": "lerna run clear",
"commit": "npx git-cz || exit 0",
"commit-retry": "npx git-cz --retry || exit 0",
"coverage": "cat ./coverage/lcov.info | coveralls",
"doc": "typedoc packages/*/src --tsconfig typedoc.json --sourcefile-url-prefix 'https://github.com/barbajs/barba/tree/main/'",
"lint": "tslint packages/*/src/** packages/*/__tests__/**",
"ls": "lerna ls",
"prepublish": "yarn run build",
"release": "lerna publish && npm run tag:next",
"release:next": "lerna publish --dist-tag next",
"report": "lerna run report",
"size": "lerna run size",
"tag:latest": "lerna run tag:latest --npm-client=npm",
"tag:next": "lerna run tag:next --npm-client=npm",
"test": "npm-run-all lint build unit e2e",
"unit": "yarn jest --coverage",
"unit:ci": "yarn jest --coverage --maxWorkers=2",
"unit:watch": "yarn jest --watch --verbose false",
"e2e": "start-server-and-test cy:server :8111 cy:run",
"e2e:watch": "start-server-and-test cy:server :8111 cy:dev",
"cy:server": "http-server . -p 8111",
"cy:run": "cypress run --browser chrome --record --key 6f43f378-ecdc-4502-9635-b6f5c205429e",
"cy:dev": "cypress open",
"watch": "npm-run-all -p build:watch unit:watch"
},
"husky": {
"hooks": {
"pre-commit": "lerna run --concurrency 1 --stream precommit",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"config": {
"commitizen": {
"path": "./node_modules/cz-ccgls"
}
}
}
================================================
FILE: packages/core/.npmignore
================================================
### Custom ###
/__e2e__
/__mocks__
/__tests__
/__web__
/jest.config.js
/mangle.json
/*.md
/.rts2*
!/README.md
!/CHANGELOG.md
================================================
FILE: packages/core/AUTHORS
================================================
Luigi De Rosa (https://luruke.com/)
Thierry Michel (https://www.epic.net/)
Xavier Foucrier (https://xavierfoucrier.dev/)
================================================
FILE: packages/core/CHANGELOG.md
================================================
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.10.3](https://github.com/barbajs/barba/compare/@barba/core@2.10.2...@barba/core@2.10.3) (2024-08-12)
### Bug Fixes
- **core:** :ambulance: hotfix event propagation ([6d35aa4](https://github.com/barbajs/barba/commit/6d35aa431673e6d37161772483f891d611fef8eb)), closes [#746](https://github.com/barbajs/barba/issues/746)
## [2.10.2](https://github.com/barbajs/barba/compare/@barba/core@2.10.0...@barba/core@2.10.2) (2024-08-02)
### Bug Fixes
- **core:** :bug: fix popstate when no link event is present ([680e2e7](https://github.com/barbajs/barba/commit/680e2e73c0a77186ae22112f1cefa2deef9eea04))
# [2.10.0](https://github.com/barbajs/barba/compare/@barba/core@2.9.7...@barba/core@2.10.0) (2024-05-10)
### Bug Fixes
- **core:** :bug: cache first page ([a45bc26](https://github.com/barbajs/barba/commit/a45bc2692802cbb36259604e11ad8cd680e4701f)), closes [#602](https://github.com/barbajs/barba/issues/602)
- **core:** :bug: fix `data-barba-history="replace"` attribute ([8e38a8f](https://github.com/barbajs/barba/commit/8e38a8f9097f68e92a1a18f42cf88edf1456d637))
- **core:** :bug: fix container replacement in the dom ([aec3143](https://github.com/barbajs/barba/commit/aec314365942c53497a05b857f7170e9bb0b0a44)), closes [#479](https://github.com/barbajs/barba/issues/479)
- **core:** :bug: fix DOMParser error on SSR ([cadba05](https://github.com/barbajs/barba/commit/cadba0512eb5459e325f7af82f210a92e05e24d5)), closes [#512](https://github.com/barbajs/barba/issues/512)
- **core:** :bug: fix request header name case ([167988d](https://github.com/barbajs/barba/commit/167988ddc67654675816ca39d8d28980c423d229))
- **core:** :bug: prevent `onLinkEnter` prefetch to cache relative URLs ([a7d15ac](https://github.com/barbajs/barba/commit/a7d15acb11f745107a4c11b5d783988a9eca7764))
- **core:** :bug: prevent assistive technology to read out the entire page ([4baef3e](https://github.com/barbajs/barba/commit/4baef3e8171c0e5b3dd98b8ca886e5ff811a7513)), closes [#681](https://github.com/barbajs/barba/issues/681)
- **core:** :bug: prevent programmatic prefetch to cache relative URLs ([a021236](https://github.com/barbajs/barba/commit/a021236668082a14d3c3c718acbc30ae0f5e9bdb))
- **core:** :bug: properly match `self` transition ([f7bd01c](https://github.com/barbajs/barba/commit/f7bd01cfdb333c1d0afad109a7f74d01adcb78f1))
- **core:** :bug: properly prevent `self` transition ([4c97b59](https://github.com/barbajs/barba/commit/4c97b59c86bc9e5ce9309621334d44849916299c)), closes [#700](https://github.com/barbajs/barba/issues/700)
- **core:** :pencil2: fix `this.barba` typo ([707c3de](https://github.com/barbajs/barba/commit/707c3de77152dad11e98cb10877a57965e561623))
- **core:** :pencil2: fix typos in tests ([a748356](https://github.com/barbajs/barba/commit/a748356daf77117a120783eee4750c16e7603ad2))
- **core:** :rotating_light: align asterisks for jsdoc ([ff837db](https://github.com/barbajs/barba/commit/ff837dbd2569d051164fd6f72cbad2919361cf84))
- **core:** :rotating_light: fix linter issues inside `core` ([5ae1432](https://github.com/barbajs/barba/commit/5ae1432d34a142154dc4a3928b7ab01a81ff232e))
- **core:** :rotating_light: fix maxlength line issue ([45df0d6](https://github.com/barbajs/barba/commit/45df0d696f69c2cfbeca6f764d1e5ae465b8d177))
- **core:** :rotating_light: sort imports alphabetically ([0ccbfda](https://github.com/barbajs/barba/commit/0ccbfdaf5c1a51c60240e4328b062ea8b63e3626))
- **core:** :rotating_light: sort variables alphabetically ([6c2c3d7](https://github.com/barbajs/barba/commit/6c2c3d70b6f63bb796a95d4778919707f63054a7))
- **core:** :white_check_mark: fix duplicate expect state ([085794b](https://github.com/barbajs/barba/commit/085794bac6fd32c2082c05c9d59c9135c0320b7f))
- **core:** :white_check_mark: fix request tests ([151abff](https://github.com/barbajs/barba/commit/151abff58dc8658ef251a96c3fb32db865322f6f))
- **core:** ✅ fix request tests ([79e207b](https://github.com/barbajs/barba/commit/79e207b4e7ff88c39a33f963d3833cfb9c2ba50b))
- **core:** 🐛 fix transition with popstate event and query string ([e27736f](https://github.com/barbajs/barba/commit/e27736fc305d0315cbf0a01f74a9209c8337a02e)), closes [#587](https://github.com/barbajs/barba/issues/587)
- **core:** 🚨 align asterisks for jsdoc ([811b3ab](https://github.com/barbajs/barba/commit/811b3ab0ea67933348228792b39240df01e3fe12))
- **core:** timeout reload, go to next page instead ([2b8f59a](https://github.com/barbajs/barba/commit/2b8f59a11a1440c4dc9c89126c511fbec4f4bffd))
### Features
- **core:** :sparkles: add `cacheFirstPage` option ([4306972](https://github.com/barbajs/barba/commit/43069722744822853dbc459aea5ab5a4b8bd924f))
- **core:** :sparkles: add `CacheStatus` to reflect Promise status ([61c28c7](https://github.com/barbajs/barba/commit/61c28c75fff686d19b03da3198776be293399e1b))
- **core:** :sparkles: add `CacheTarget` type ([a4e9045](https://github.com/barbajs/barba/commit/a4e9045a7ad14cf40dae7bf3084cd8e9a9e89cd7))
- **core:** :sparkles: add `getTarget` method ([1d187de](https://github.com/barbajs/barba/commit/1d187de72e11b2360b1e1f6c9f19a38d3fd94e97))
- **core:** :sparkles: add `Headers` module ([141249d](https://github.com/barbajs/barba/commit/141249d3764e5791530e265793ec72722d67958d))
- **core:** :sparkles: add `IDomSibling` interface ([d3acdb8](https://github.com/barbajs/barba/commit/d3acdb8dec3a494b5a17643312f778921155d22e))
- **core:** :sparkles: add `IResponse` interface ([c2fa15a](https://github.com/barbajs/barba/commit/c2fa15acfe3d7c8b08659dd0da5d6b409e9609ad))
- **core:** :sparkles: add a method to retrieve absolute href from URL ([ad96797](https://github.com/barbajs/barba/commit/ad967972a41a324dd9128855225f41bae6142587))
- **core:** :sparkles: allow `CacheStatus` to be retrieved ([9970f21](https://github.com/barbajs/barba/commit/9970f216c4e629783a7f2a4f828bf8ca707fc70c))
- **core:** :sparkles: allow custom `data` when adding to history ([2eaab1c](https://github.com/barbajs/barba/commit/2eaab1cf345462692951b9b09418484823e55bbb))
- **core:** :sparkles: allow custom data in `barba.history` ([920880a](https://github.com/barbajs/barba/commit/920880a8573ee9fc1eb03fd75cce08c872be0d27)), closes [#630](https://github.com/barbajs/barba/issues/630)
- **core:** :sparkles: allow programmatic `barba.history` management ([e1e4b5f](https://github.com/barbajs/barba/commit/e1e4b5f270cd9e08aa4981a89bb744a8834f41c1)), closes [#601](https://github.com/barbajs/barba/issues/601)
- **core:** :sparkles: expose `getQuery` and `getHash` methods ([4456f4b](https://github.com/barbajs/barba/commit/4456f4b7d03cd9933a0ea43dd722298be82b9088))
- **core:** :sparkles: implement `getSibling` method ([4bf2802](https://github.com/barbajs/barba/commit/4bf280265f21e4e5b6a628982d4155be0a6467a9))
- **core:** :sparkles: pass the trigger event through `hooks` ([a2fef11](https://github.com/barbajs/barba/commit/a2fef11e7947667ff6386bd1e4ef680c30aaadeb)), closes [#622](https://github.com/barbajs/barba/issues/622)
- **core:** :sparkles: properly manage server response ([ae94e2c](https://github.com/barbajs/barba/commit/ae94e2c929e20ef527f7c91fb2d006da7ae78a19))
- **core:** :sparkles: resolve `CacheRequest` with `IResponse` instead ([1061245](https://github.com/barbajs/barba/commit/106124553200a6f8c30fe8bdc562c12d38e56b2f))
- **core:** :sparkles: store `target` in the cache based on server response ([f321926](https://github.com/barbajs/barba/commit/f3219262bd161075d7478be39b60c4a5d3ae59b2))
- **core:** :sparkles: store response url through `IResponse` interface ([1963609](https://github.com/barbajs/barba/commit/19636096af3128d9ebbf73e7d845a593f13000e2))
- **core:** :sparkles: update cache `status` to reflect Promise state ([54edab1](https://github.com/barbajs/barba/commit/54edab19834f9e65024f18651c0634ca32f08e0b))
- **core:** ♻️ add headers type definitions ([5d2f13f](https://github.com/barbajs/barba/commit/5d2f13f098aed2a407dd664a66300c49c62362c2))
- **core:** ♻️ import `Headers` module ([1b6c418](https://github.com/barbajs/barba/commit/1b6c4181030c1e956fa43708f166f57315d6788d))
- **core:** ♻️ pass headers to the `request` utility ([60fa820](https://github.com/barbajs/barba/commit/60fa8204ca75c3a925c36d7e8f2c44a550b9c075))
- **core:** ✨ set custom request headers ([0edbffe](https://github.com/barbajs/barba/commit/0edbffea5d540ed35f1f85094d758c280a6e4d8d))
## [2.9.7](https://github.com/barbajs/barba/compare/@barba/core@2.9.6...@barba/core@2.9.7) (2020-01-16)
### Bug Fixes
- **core:** :bug: fix once only transition resolved for page ([0e52e61](https://github.com/barbajs/barba/commit/0e52e616e9964ad98f28239b1341a71cf1d29f4a)), closes [#483](https://github.com/barbajs/barba/issues/483)
## [2.9.6](https://github.com/barbajs/barba/compare/@barba/core@2.9.5...@barba/core@2.9.6) (2019-12-12)
### Bug Fixes
- **core:** :bug: fix route (object) resolution ([1fb344f](https://github.com/barbajs/barba/commit/1fb344f9f07fbe58c5893b09f59d471704c0c521))
## [2.9.5](https://github.com/barbajs/barba/compare/@barba/core@2.9.4...@barba/core@2.9.5) (2019-12-09)
### Bug Fixes
- **core:** :bug: filter transition errors from request errors ([281c85f](https://github.com/barbajs/barba/commit/281c85fc7bbaf3d51ee58653468c48b2404152ea)), closes [#475](https://github.com/barbajs/barba/issues/475)
## [2.9.4](https://github.com/barbajs/barba/compare/@barba/core@2.9.3...@barba/core@2.9.4) (2019-12-09)
### Bug Fixes
- **core:** :bug: fix cache management with ignore option ([d801813](https://github.com/barbajs/barba/commit/d801813976a130d41b3261e7de8f0bcdf5dcd581)), closes [#470](https://github.com/barbajs/barba/issues/470)
## [2.9.3](https://github.com/barbajs/barba/compare/@barba/core@2.9.2...@barba/core@2.9.3) (2019-12-09)
### Bug Fixes
- **core:** :recycle: refactor history states ([08c83b8](https://github.com/barbajs/barba/commit/08c83b857d8ab3f7826631968afaabf76e1a2e87)), closes [#473](https://github.com/barbajs/barba/issues/473) [#472](https://github.com/barbajs/barba/issues/472)
## [2.9.2](https://github.com/barbajs/barba/compare/@barba/core@2.9.1...@barba/core@2.9.2) (2019-11-25)
### Bug Fixes
- **root:** :art: improve typings for TS ([48f0637](https://github.com/barbajs/barba/commit/48f0637))
## [2.9.1](https://github.com/barbajs/barba/compare/@barba/core@2.9.0...@barba/core@2.9.1) (2019-11-25)
### Bug Fixes
- **core:** :rotating_light: fix TS errors, improve TS defs ([a48acd2](https://github.com/barbajs/barba/commit/a48acd2)), closes [#468](https://github.com/barbajs/barba/issues/468)
# [2.9.0](https://github.com/barbajs/barba/compare/@barba/core@2.8.0...@barba/core@2.9.0) (2019-11-25)
### Bug Fixes
- **core:** :bug: hooks: context can not be undefined ([f6bb536](https://github.com/barbajs/barba/commit/f6bb536)), closes [#468](https://github.com/barbajs/barba/issues/468)
### Features
- **core:** :sparkles: add replace history via data-attribute ([272a43f](https://github.com/barbajs/barba/commit/272a43f)), closes [#460](https://github.com/barbajs/barba/issues/460)
# [2.8.0](https://github.com/barbajs/barba/compare/@barba/core@2.7.2...@barba/core@2.8.0) (2019-11-06)
### Bug Fixes
- **core:** :bug: compare ports for sameUrl prevent check ([e2a84e4](https://github.com/barbajs/barba/commit/e2a84e4)), closes [#463](https://github.com/barbajs/barba/issues/463)
- **core:** :bug: popstate with unknown state (null) ([3369633](https://github.com/barbajs/barba/commit/3369633)), closes [#456](https://github.com/barbajs/barba/issues/456) [#466](https://github.com/barbajs/barba/issues/466)
- **core:** :ok_hand: resolve once transitions ([20cafe1](https://github.com/barbajs/barba/commit/20cafe1)), closes [#439](https://github.com/barbajs/barba/issues/439)
### Features
- **core:** :loud_sound: add/improve error logs ([e67a17b](https://github.com/barbajs/barba/commit/e67a17b)), closes [#447](https://github.com/barbajs/barba/issues/447)
## [2.7.2](https://github.com/barbajs/barba/compare/@barba/core@2.7.1...@barba/core@2.7.2) (2019-11-05)
### Bug Fixes
- **core:** :heavy_minus_sign: remove 'path' for URL resolution ([3875d0c](https://github.com/barbajs/barba/commit/3875d0c)), closes [#465](https://github.com/barbajs/barba/issues/465)
- **root:** :bug: fix context for views and add to transitions ([9054673](https://github.com/barbajs/barba/commit/9054673)), closes [#467](https://github.com/barbajs/barba/issues/467)
## [2.7.1](https://github.com/barbajs/barba/compare/@barba/core@2.7.0...@barba/core@2.7.1) (2019-10-27)
**Note:** Version bump only for package @barba/core
# [2.7.0](https://github.com/barbajs/barba/compare/@barba/core@2.6.1...@barba/core@2.7.0) (2019-10-27)
### Bug Fixes
- **core:** :bug: fix container + dom sibling insertion ([7f349a7](https://github.com/barbajs/barba/commit/7f349a7)), closes [#449](https://github.com/barbajs/barba/issues/449)
- **core:** :ok_hand: move after hooks ([42742ea](https://github.com/barbajs/barba/commit/42742ea)), closes [#455](https://github.com/barbajs/barba/issues/455)
### Features
- **core:** :sparkles: add preventRunning option ([93f0b50](https://github.com/barbajs/barba/commit/93f0b50)), closes [#414](https://github.com/barbajs/barba/issues/414)
## [2.6.1](https://github.com/barbajs/barba/compare/@barba/core@2.6.0...@barba/core@2.6.1) (2019-10-22)
### Bug Fixes
- **core:** :ambulance: fix URL with query/hash ([f5e639c](https://github.com/barbajs/barba/commit/f5e639c)), closes [#445](https://github.com/barbajs/barba/issues/445)
- **core:** :recycle: improve url/href/path management ([159afdc](https://github.com/barbajs/barba/commit/159afdc))
# [2.6.0](https://github.com/barbajs/barba/compare/@barba/core@2.5.1...@barba/core@2.6.0) (2019-08-22)
### Features
- **core:** :alembic: store scroll position in history ([0fb28e2](https://github.com/barbajs/barba/commit/0fb28e2))
## [2.5.1](https://github.com/barbajs/barba/compare/@barba/core@2.5.0...@barba/core@2.5.1) (2019-08-22)
### Bug Fixes
- **core:** :bug: keep container position ([5482154](https://github.com/barbajs/barba/commit/5482154))
# [2.5.0](https://github.com/barbajs/barba/compare/@barba/core@2.4.0...@barba/core@2.5.0) (2019-08-22)
### Features
- **core:** :ok_hand: replace popstate with back/forward ([c665052](https://github.com/barbajs/barba/commit/c665052))
# [2.4.0](https://github.com/barbajs/barba/compare/@barba/core@2.3.16...@barba/core@2.4.0) (2019-08-02)
### Features
- **core:** :sparkles: add history size ([3b8d7fd](https://github.com/barbajs/barba/commit/3b8d7fd))
## [2.3.16](https://github.com/barbajs/barba/compare/@barba/core@2.3.15...@barba/core@2.3.16) (2019-08-01)
### Bug Fixes
- **core:** :bug: Fix global hooks (before|afterEnter) on first load ([e948166](https://github.com/barbajs/barba/commit/e948166)), closes [#393](https://github.com/barbajs/barba/issues/393)
## [2.3.15](https://github.com/barbajs/barba/compare/@barba/core@2.3.14...@barba/core@2.3.15) (2019-07-17)
### Bug Fixes
- **core:** :ok_hand: view hook on page load ([c631b54](https://github.com/barbajs/barba/commit/c631b54)), closes [#393](https://github.com/barbajs/barba/issues/393)
## [2.3.14](https://github.com/barbajs/barba/compare/@barba/core@2.3.13...@barba/core@2.3.14) (2019-07-16)
### Bug Fixes
- **root:** :mute: remove print version ([be5aa73](https://github.com/barbajs/barba/commit/be5aa73)), closes [#415](https://github.com/barbajs/barba/issues/415)
## [2.3.13](https://github.com/barbajs/barba/compare/@barba/core@2.3.12...@barba/core@2.3.13) (2019-07-16)
### Bug Fixes
- **core:** :bug: Clean url extend ([7667a8d](https://github.com/barbajs/barba/commit/7667a8d))
- **core:** :bug: fix link with no href attribute ([e434ecb](https://github.com/barbajs/barba/commit/e434ecb))
## [2.3.12](https://github.com/barbajs/barba/compare/@barba/core@2.3.11...@barba/core@2.3.12) (2019-06-26)
### Bug Fixes
- **core:** :ok_hand: improve support of SVG links ([19e7e5d](https://github.com/barbajs/barba/commit/19e7e5d))
## [2.3.11](https://github.com/barbajs/barba/compare/@barba/core@2.3.10...@barba/core@2.3.11) (2019-06-25)
### Bug Fixes
- **core:** :bug: make page hook async ([10e66d9](https://github.com/barbajs/barba/commit/10e66d9))
## [2.3.10](https://github.com/barbajs/barba/compare/@barba/core@2.3.9...@barba/core@2.3.10) (2019-06-11)
### Bug Fixes
- **core:** :bug: remove "force repaint" when new container is added ([5a34322](https://github.com/barbajs/barba/commit/5a34322))
- **core:** :construction: fix "glitch" when new container added ([1286bf9](https://github.com/barbajs/barba/commit/1286bf9))
## [2.3.9](https://github.com/barbajs/barba/compare/@barba/core@2.3.8...@barba/core@2.3.9) (2019-04-29)
**Note:** Version bump only for package @barba/core
## [2.3.8](https://github.com/barbajs/barba/compare/@barba/core@2.3.7...@barba/core@2.3.8) (2019-04-29)
### Bug Fixes
- **core:** :bug: fix sameUrl with query params ([fa79a6a](https://github.com/barbajs/barba/commit/fa79a6a)), closes [#389](https://github.com/barbajs/barba/issues/389)
## [2.3.7](https://github.com/barbajs/barba/compare/@barba/core@2.3.6...@barba/core@2.3.7) (2019-04-29)
### Bug Fixes
- **core:** :bug: fix glitch on containers add/remove ([374660c](https://github.com/barbajs/barba/commit/374660c))
## [2.3.6](https://github.com/barbajs/barba/compare/@barba/core@2.3.5...@barba/core@2.3.6) (2019-04-29)
**Note:** Version bump only for package @barba/core
## [2.3.5](https://github.com/barbajs/barba/compare/@barba/core@2.3.4...@barba/core@2.3.5) (2019-04-29)
### Bug Fixes
- **core:** :construction: fix history ([36d3393](https://github.com/barbajs/barba/commit/36d3393))
## [2.3.4](https://github.com/barbajs/barba/compare/@barba/core@2.3.3...@barba/core@2.3.4) (2019-04-29)
### Bug Fixes
- **core:** :bug: fix object rule with no value ([4014fd8](https://github.com/barbajs/barba/commit/4014fd8))
## [2.3.3](https://github.com/barbajs/barba/compare/@barba/core@2.3.2...@barba/core@2.3.3) (2019-04-23)
### Bug Fixes
- **core:** :bug: update title with "next" ([f8c1940](https://github.com/barbajs/barba/commit/f8c1940)), closes [#384](https://github.com/barbajs/barba/issues/384)
## [2.3.2](https://github.com/barbajs/barba/compare/@barba/core@2.3.1...@barba/core@2.3.2) (2019-04-20)
### Bug Fixes
- **core:** :bug: remove current container at the end ([f6fab91](https://github.com/barbajs/barba/commit/f6fab91))
## [2.3.1](https://github.com/barbajs/barba/compare/@barba/core@2.3.0...@barba/core@2.3.1) (2019-04-16)
### Bug Fixes
- **core:** :bug: do not cache rendered HTML ([0cc4b86](https://github.com/barbajs/barba/commit/0cc4b86)), closes [#383](https://github.com/barbajs/barba/issues/383)
# [2.3.0](https://github.com/barbajs/barba/compare/@barba/core@2.2.0...@barba/core@2.3.0) (2019-04-14)
### Features
- **core:** :sparkles: add programmatically prefetch ([7b95ffd](https://github.com/barbajs/barba/commit/7b95ffd))
# [2.2.0](https://github.com/barbajs/barba/compare/@barba/core@2.1.3...@barba/core@2.2.0) (2019-04-14)
### Features
- **core:** :art: allow global hooks to be asynchronous ([be5dccf](https://github.com/barbajs/barba/commit/be5dccf))
## [2.1.3](https://github.com/barbajs/barba/compare/@barba/core@2.1.2...@barba/core@2.1.3) (2019-04-13)
### Bug Fixes
- **core:** :loud_sound: print version ([24dd2ea](https://github.com/barbajs/barba/commit/24dd2ea))
### Reverts
- **root:** :bug: revert failed release ([2b8a1ef](https://github.com/barbajs/barba/commit/2b8a1ef))
## [2.1.3](https://github.com/barbajs/barba/compare/@barba/core@2.1.2...@barba/core@2.1.3) (2019-04-13)
### Bug Fixes
- **core:** :loud_sound: print version ([24dd2ea](https://github.com/barbajs/barba/commit/24dd2ea))
## [2.1.2](https://github.com/barbajs/barba/compare/@barba/core@2.1.1...@barba/core@2.1.2) (2019-04-13)
### Bug Fixes
- **core:** :mute: remove debug logs ([f4ce952](https://github.com/barbajs/barba/commit/f4ce952))
## [2.1.1](https://github.com/barbajs/barba/compare/@barba/core@2.1.0...@barba/core@2.1.1) (2019-04-13)
### Bug Fixes
- **core:** :bug: fix cache not working ([a01e122](https://github.com/barbajs/barba/commit/a01e122))
- **core:** :bug: fix hook order ([716b062](https://github.com/barbajs/barba/commit/716b062))
- **core:** :bug: fix hooks order in sync mode true ([b3c92d1](https://github.com/barbajs/barba/commit/b3c92d1))
- **core:** :bug: fix popstate navigation ([f78ee11](https://github.com/barbajs/barba/commit/f78ee11)), closes [#359](https://github.com/barbajs/barba/issues/359)
- **core:** :bug: fix sameUrl + anchors ([039f5d9](https://github.com/barbajs/barba/commit/039f5d9)), closes [#359](https://github.com/barbajs/barba/issues/359)
- **core:** :bug: fix timeout error ([70b7805](https://github.com/barbajs/barba/commit/70b7805)), closes [#373](https://github.com/barbajs/barba/issues/373)
- **core:** :bug: fix view.beforeEnter on barba ready ([5a09470](https://github.com/barbajs/barba/commit/5a09470)), closes [#360](https://github.com/barbajs/barba/issues/360)
- **core:** :bug: fix wrong combo namespace / view hooks ([3c775a3](https://github.com/barbajs/barba/commit/3c775a3)), closes [#351](https://github.com/barbajs/barba/issues/351)
- **core:** :checkered_flag: fix InvalidStateError on IE ([b9eece9](https://github.com/barbajs/barba/commit/b9eece9)), closes [#371](https://github.com/barbajs/barba/issues/371)
- **core:** :green_apple: fix img[srcset] parsing ([8afe945](https://github.com/barbajs/barba/commit/8afe945)), closes [#362](https://github.com/barbajs/barba/issues/362)
- **core:** :ok_hand: add Accept header ([94962ef](https://github.com/barbajs/barba/commit/94962ef))
- **core:** :ok_hand: fix `beforeEnter` view hook ([0d11e44](https://github.com/barbajs/barba/commit/0d11e44))
- **core:** :ok_hand: make main transition hooks public ([2c0cc28](https://github.com/barbajs/barba/commit/2c0cc28))
- **core:** :ok_hand: make onRequestError public ([61193ad](https://github.com/barbajs/barba/commit/61193ad))
# 2.1.0 (2019-03-17)
### Bug Fixes
- **core:** :bug: append next container correctly on sync mode ([dc62bd3](https://github.com/barbajs/barba/commit/dc62bd3)), closes [#4](https://github.com/barbajs/barba/issues/4)
- **core:** :bug: fix `xlink:href` with SVG ([19ecd81](https://github.com/barbajs/barba/commit/19ecd81)), closes [#1](https://github.com/barbajs/barba/issues/1)
- **css:** :bug: fix css with next tick ([63642bf](https://github.com/barbajs/barba/commit/63642bf))
- **prefetch:** :bug: fix requestError ([33c213b](https://github.com/barbajs/barba/commit/33c213b))
- **root:** :bug: force publish ([ddb8798](https://github.com/barbajs/barba/commit/ddb8798))
- **root:** :ok_hand: replace error with warning when no transition ([661801e](https://github.com/barbajs/barba/commit/661801e))
- :bug: fix case issues ([c6adcb3](https://github.com/barbajs/barba/commit/c6adcb3))
### Features
- **core:** :sparkles: add prevent custom + update README ([2fb4ec6](https://github.com/barbajs/barba/commit/2fb4ec6))
- **css:** :recycle: add transitionend logic + big refactoring ([b775358](https://github.com/barbajs/barba/commit/b775358))
- **css:** :tada: initial commit ([aed8206](https://github.com/barbajs/barba/commit/aed8206))
- **root:** :sparkles: add logger + fixes ([6db3875](https://github.com/barbajs/barba/commit/6db3875))
- **router:** :sparkles: add multiple properties to `route` ([4e92c83](https://github.com/barbajs/barba/commit/4e92c83))
================================================
FILE: packages/core/LICENSE
================================================
MIT License
Copyright (c) 2024 Luigi De Rosa, Thierry Michel, Xavier Foucrier
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: packages/core/README.md
================================================
# @barba/core
[](https://www.npmjs.com/package/@barba/core)
[](https://github.com/barbajs/barba/network/dependencies)
> TBD ([GitHub repo](https://github.com/barbajs/barba.js))
## Install
Using npm:
```sh
npm install --save-dev @barba/core
```
or using yarn:
```sh
yarn add @barba/core --dev
```
================================================
FILE: packages/core/__e2e__/container.spec.js
================================================
/* eslint-disable cypress/no-unnecessary-waiting */
describe('Transition', () => {
it('adds container at the right place', () => {
cy.prepare('/container.html', 'container', 'container');
cy.get('[data-test=sibling]').as('sibling');
cy.get('[data-test=link]').click();
cy.final('/page.html', 'page', 'page');
cy.get('@wrapper')
.children()
.eq(1)
.should('have.attr', 'data-test-container', 'next');
cy.get('@wrapper')
.children()
.eq(2)
.should('have.attr', 'data-test', 'sibling');
});
it('adds container at the right place [sync]', () => {
cy.prepare('/container.html', 'container', 'container');
cy.get('[data-test=sibling]').as('sibling');
cy.get('[data-test="link.sync"]').click();
cy.final('/page.html', 'page', 'page');
cy.get('@wrapper')
.children()
.eq(1)
.should('have.attr', 'data-test-container', 'next');
cy.get('@wrapper')
.children()
.eq(2)
.should('have.attr', 'data-test', 'sibling');
});
});
================================================
FILE: packages/core/__e2e__/default.spec.js
================================================
/* eslint-disable cypress/no-unnecessary-waiting */
describe('Transition', () => {
it('works', () => {
cy.prepare('/index.html', 'home', 'home');
cy.wait(1000); // Wait for once complete
// Click link
cy.get('[data-test=link]').click();
cy.final('/page.html', 'page', 'page');
});
});
================================================
FILE: packages/core/__e2e__/hooks.spec.js
================================================
/* eslint-disable no-mixed-operators, cypress/no-unnecessary-waiting */
const onceHooks = [
'global:beforeEnter',
// 'global:before',
// 'before',
'global:beforeOnce',
'beforeOnce',
'global:once',
'once',
'global:afterOnce',
'afterOnce',
// 'global:after',
// 'after',
'global:afterEnter',
];
const hooksDefault = [
...onceHooks,
'global:before',
'before',
'global:beforeLeave',
'beforeLeave',
'global:leave',
'leave',
'global:afterLeave',
'afterLeave',
'global:beforeEnter',
'beforeEnter',
'global:enter',
'enter',
'global:afterEnter',
'afterEnter',
'global:after',
'after',
];
const hooksSync = [
...onceHooks,
'global:before',
'before',
'global:beforeLeave',
'beforeLeave',
'global:beforeEnter',
'beforeEnter',
'global:leave',
'global:enter',
'leave',
'enter',
'global:afterLeave',
'afterLeave',
'global:afterEnter',
'afterEnter',
'global:after',
'after',
];
beforeEach(() => {
cy.prepare('/index.html', 'home', 'home');
cy.get('[data-test="hooks-list"]').as('hooks'); // Alias to @hooks
});
afterEach(() => {
cy.final('/page.html', 'page', 'page');
});
describe('Hooks', () => {
it('have default order', () => {
cy.wait(1000); // Wait for once complete
// Click link
cy.get('[data-test="link.hooks"]').click();
// Checks…
hooksDefault.forEach((name, i) => {
cy.get('@hooks')
.find(`:nth-child(${i + 1})`)
.should('contain', name);
});
});
it('have sync order', () => {
cy.wait(1000); // Wait for once complete
// Click link
cy.get('[data-test="link.hooks-sync"]').click();
// Checks…
hooksSync.forEach((name, i) => {
cy.get('@hooks')
.find(`:nth-child(${i + 1})`)
.should('contain', name);
});
});
});
================================================
FILE: packages/core/__e2e__/href.spec.js
================================================
/* eslint-disable cypress/no-unnecessary-waiting */
describe('Transition', () => {
const origin = 'http://localhost:8111';
const prefix = 'packages/core/__web__';
const page = 'page.html';
const query = '?query=string';
const hash = '#hash';
it('default URL', () => {
cy.prepare('/href.html', 'href', 'href');
cy.get('[data-test=link]').click();
cy.location().should(loc => {
expect(loc.href).to.eq(`${origin}/${prefix}/${page}`);
expect(loc.toString()).to.eq(`${origin}/${prefix}/${page}`);
expect(loc.pathname).to.eq(`/${prefix}/${page}`);
});
cy.final('/page.html', 'page', 'page');
});
it('query string URL', () => {
cy.prepare('/href.html', 'href', 'href');
cy.get('[data-test=query]').click();
cy.location().should(loc => {
expect(loc.href).to.eq(`${origin}/${prefix}/${page}${query}`);
expect(loc.toString()).to.eq(`${origin}/${prefix}/${page}${query}`);
expect(loc.pathname).to.eq(`/${prefix}/${page}`);
expect(loc.search).to.eq(query);
});
cy.final('/page.html', 'page', 'page');
});
it('hash URL', () => {
cy.prepare('/href.html', 'href', 'href');
cy.get('[data-test=hash]').click();
cy.location().should(loc => {
expect(loc.href).to.eq(`${origin}/${prefix}/${page}${hash}`);
expect(loc.toString()).to.eq(`${origin}/${prefix}/${page}${hash}`);
expect(loc.pathname).to.eq(`/${prefix}/${page}`);
expect(loc.hash).to.eq(hash);
});
cy.final('/page.html', 'page', 'page');
});
it('hash + query URL', () => {
cy.prepare('/href.html', 'href', 'href');
cy.get('[data-test=complex]').click();
cy.location().should(loc => {
expect(loc.href).to.eq(`${origin}/${prefix}/${page}${query}${hash}`);
expect(loc.toString()).to.eq(
`${origin}/${prefix}/${page}${query}${hash}`
);
expect(loc.pathname).to.eq(`/${prefix}/${page}`);
expect(loc.search).to.eq(query);
expect(loc.hash).to.eq(hash);
});
cy.final('/page.html', 'page', 'page');
});
});
================================================
FILE: packages/core/__e2e__/views.spec.js
================================================
/* eslint-disable no-mixed-operators, cypress/no-unnecessary-waiting */
const loadHooks = ['beforeEnter', 'afterEnter'];
const transitionHooks = [
'beforeLeave',
'afterLeave',
'beforeEnter',
'afterEnter',
];
beforeEach(() => {
cy.prepare('/views.html', 'home', 'home');
cy.get('[data-test="hooks-list"]').as('hooks'); // Alias to @hooks
});
afterEach(() => {
cy.final('/page.html', 'page', 'page');
});
describe('Views hooks', () => {
it('have default order', () => {
cy.wait(1000); // Wait for once complete
// Checks…
loadHooks.forEach((name, i) => {
cy.get('@hooks')
.find(`:nth-child(${i + 1})`)
.should('contain', name);
});
// Click link
cy.get('[data-test="link.hooks"]').click();
// Checks…
transitionHooks.forEach((name, i) => {
const j = i + loadHooks.length;
cy.get('@hooks')
.find(`:nth-child(${j + 1})`)
.should('contain', name);
});
});
// it('have sync order', () => {
// cy.wait(1000); // Wait for once complete
// // Click link
// cy.get('[data-test="link.hooks-sync"]').click();
// // Checks…
// hooksSync.forEach((name, i) => {
// cy.get('@hooks')
// .find(`:nth-child(${i + 1})`)
// .should('contain', name);
// });
// });
});
================================================
FILE: packages/core/__mocks__/barba.ts
================================================
import barba from '../src';
import { ITransitionPage } from '../src/defs';
/**
* Init barba with basic DOM for testing
*/
export function init(transitions: ITransitionPage[] = []): any {
const wrapper = document.createElement('div');
const container = document.createElement('div');
const link = document.createElement('a');
const span = document.createElement('span');
const namespace = 'current';
const mouseover = document.createEvent('HTMLEvents');
const click = document.createEvent('HTMLEvents');
wrapper.dataset.barba = 'wrapper';
container.dataset.barba = 'container';
container.dataset.barbaNamespace = namespace;
document.title = 'Current page';
document.body.appendChild(wrapper);
wrapper.appendChild(container);
container.appendChild(link);
link.appendChild(span);
mouseover.initEvent('mouseover', true, false);
click.initEvent('click', true, false);
barba.init({ transitions });
return { wrapper, container, link, span, mouseover, click };
}
================================================
FILE: packages/core/__mocks__/transitions.ts
================================================
import { ITransitionPage } from '../src/defs';
const namespace = 'n';
const route = 'r';
const custom = () => true;
const unamed: ITransitionPage[] = [
/* 0000 */ {}, // Nothing
/* 0010 */ { namespace }, // Namespace
/* 0011 */ { from: { namespace } },
/* 0012 */ { to: { namespace } },
/* 0013 */ { from: { namespace }, to: { namespace } },
/* 0100 */ { route }, // Route
/* 0101 */ { from: { route } },
/* 0102 */ { to: { route } },
/* 0103 */ { from: { route }, to: { route } },
/* 0110 */ { route, namespace }, // Route + namespace
/* 0111 */ { from: { route, namespace } }, // 10
/* 0112 */ { to: { route, namespace } },
/* 0113 */ { from: { route, namespace }, to: { route, namespace } },
/* 1000 */ { custom }, // Custom
/* 1001 */ { from: { custom } },
/* 1002 */ { to: { custom } },
/* 1003 */ { from: { custom }, to: { custom } }, // 16
/* 1010 */ { custom, namespace }, // Custom + namespace
/* 1011 */ { from: { custom, namespace } },
/* 1012 */ { to: { custom, namespace } },
/* 1013 */ { from: { custom, namespace }, to: { custom, namespace } },
/* 1100 */ { custom, route }, // Custom + route
/* 1101 */ { from: { custom, route } },
/* 1102 */ { to: { custom, route } },
/* 1103 */ { from: { custom, route }, to: { custom, route } },
/* 1110 */ { custom, route, namespace }, // Custom + route + namespace
/* 1111 */ { from: { custom, route, namespace } },
/* 1112 */ { to: { custom, route, namespace } },
/* 1113 */ {
from: { custom, route, namespace },
to: { custom, route, namespace },
},
];
const named: ITransitionPage[] = unamed.map((t, i) => {
t.name = i.toString();
return t;
});
export default named;
================================================
FILE: packages/core/__tests__/core/core.click.test.ts
================================================
import { init } from '../../__mocks__/barba';
import barba from '../../src';
const { link, span, click } = init();
// Mocks
barba.page = jest.fn();
afterEach(() => {
(global as any).jsdom.reconfigure({ url: 'http://localhost/' });
});
it('handle link click', () => {
link.href = 'foo';
span.dispatchEvent(click);
expect(barba.page).toHaveBeenCalledTimes(1);
});
it('handle link click with same url', () => {
link.href = 'http://localhost/';
span.dispatchEvent(click);
expect(barba.page).toHaveBeenCalledTimes(0);
});
it('handle link click with prevent', () => {
link.href = 'foo';
link.dataset.barbaPrevent = '';
span.dispatchEvent(click);
expect(barba.page).toHaveBeenCalledTimes(0);
});
it('handle link click with transition running', () => {
barba.go = jest.fn();
barba.transitions.isRunning = true;
link.href = 'foo';
delete link.dataset.barbaPrevent;
barba.preventRunning = false;
span.dispatchEvent(click);
barba.preventRunning = true;
span.dispatchEvent(click);
expect(barba.go).toHaveBeenCalledTimes(1);
});
================================================
FILE: packages/core/__tests__/core/core.enter.test.ts
================================================
import waitForExpect from 'wait-for-expect';
import xhrMock from 'xhr-mock';
import { init } from '../../__mocks__/barba';
import barba from '../../src';
import { IUrlFull } from '../../src/defs';
import { parse } from '../../src/utils/url';
const { link, span, mouseover } = init();
const sameUrl = 'http://localhost/';
const sameHtml = `
Current page
* ## Logger.
*
* - Display informations via the console
*
* @module core/modules/Logger
* @preferred
*/
/***/
/**
* Log levels, all lower level messages are printed
*
* 0. mute
* 1. error = `console.error()`
* 2. warning= `console.warn()`
* 3. info = `console.info()`
* 4. debug = `console.log()`
*/
export enum LogLevels {
off = 0,
error = 1,
warning = 2,
info = 3,
debug = 4,
}
/**
* Global log level
*/
let _level: number = LogLevels.off;
export class Logger {
/**
* Get global log level.
*/
public static getLevel(): number {
return _level;
}
/**
* Set global log level.
*/
public static setLevel(name: keyof typeof LogLevels): number {
_level = LogLevels[name];
return _level;
}
/**
* Log "prefix".
*/
private _source: string;
/**
* Creates an instance of Logger.
*/
constructor(source: string) {
this._source = source;
}
/**
* Permanent, unremovable log.
*/
// public print(...objects: any[]): void {
// this._log(console.info, LogLevels.off, objects);
// }
/**
* Error log.
*/
public error(...objects: any[]): void {
this._log(console.error, LogLevels.error, objects);
}
/**
* Warn log.
*/
public warn(...objects: any[]): void {
this._log(console.warn, LogLevels.warning, objects);
}
/**
* Info log.
*/
public info(...objects: any[]): void {
this._log(console.info, LogLevels.info, objects);
}
/**
* Debug log.
*/
public debug(...objects: any[]): void {
this._log(console.log, LogLevels.debug, objects);
}
/**
* Internal logger.
*/
private _log(fn: () => void, level: number, objects: any[]): void {
if (level <= Logger.getLevel()) {
fn.apply(console, ([`[${this._source}] `].concat(objects) as unknown) as [
]);
}
}
}
================================================
FILE: packages/core/src/modules/Prevent.ts
================================================
/**
* @barba/core/modules/prevent
*
* ## Prevent checks.
*
* - Gathers all the tests that allow Barba to work and play transitions
*
* @module core/modules/prevent
* @preferred
*/
/***/
// Definitions
import { IgnoreOption, Link, PreventCheck } from '../defs';
// Schemas
import { schemaAttribute } from '../schemas/attribute';
// Utils
import { url } from '../utils';
// Modules
import { Ignore } from './Ignore';
/**
* Make sure the browser supports `history.pushState`.
*/
const pushState: PreventCheck = () => !window.history.pushState;
/**
* Make sure there is an `el` and `href`.
*/
const exists: PreventCheck = ({ el, href }) => !el || !href;
/**
* If the user is pressing ctrl + click, the browser will open a new tab.
*/
const newTab: PreventCheck = ({ event }) =>
(event as KeyboardEvent).which > 1 ||
(event as KeyboardEvent).metaKey ||
(event as KeyboardEvent).ctrlKey ||
(event as KeyboardEvent).shiftKey ||
(event as KeyboardEvent).altKey;
/**
* If the link has `_blank` target.
*/
const blank: PreventCheck = ({ el }) =>
el.hasAttribute('target') && (el as Link).target === '_blank';
/**
* If the domain is the same (in order to avoid pushState cross origin security problem).
* Note: SVGAElement do not have `protocol` neither `hostname` properties.
*/
const corsDomain: PreventCheck = ({ el }) =>
((el as HTMLAnchorElement).protocol !== undefined &&
window.location.protocol !== (el as HTMLAnchorElement).protocol) ||
((el as HTMLAnchorElement).hostname !== undefined &&
window.location.hostname !== (el as HTMLAnchorElement).hostname);
/**
* If the port is the same.
* Note: SVGAElement do not have `port` property.
*/
const corsPort: PreventCheck = ({ el }) =>
(el as HTMLAnchorElement).port !== undefined &&
url.getPort() !== url.getPort((el as HTMLAnchorElement).href);
/**
* If the link has download attribute.
*/
const download: PreventCheck = ({ el }) =>
el.getAttribute && typeof el.getAttribute('download') === 'string';
/**
* If the links contains [data-barba-prevent] or [data-barba-prevent="self"].
*/
const preventSelf: PreventCheck = ({ el }) =>
el.hasAttribute(`${schemaAttribute.prefix}-${schemaAttribute.prevent}`);
/**
* If some link ancestor contains [data-barba-prevent="all"].
*/
const preventAll: PreventCheck = ({ el }) =>
Boolean(
el.closest(`[${schemaAttribute.prefix}-${schemaAttribute.prevent}="all"]`)
);
/**
* If the link is the current URL.
*
* > Not in the test suite.
*/
const sameUrl: PreventCheck = ({ href }) =>
url.clean(href) === url.clean() && url.getPort(href) === url.getPort();
export class Prevent extends Ignore {
public suite: string[] = [];
public tests: Map = new Map();
constructor(ignore: IgnoreOption) {
super(ignore);
this.init();
}
public init(): void {
// Add defaults
this.add('pushState', pushState);
this.add('exists', exists);
this.add('newTab', newTab);
this.add('blank', blank);
this.add('corsDomain', corsDomain);
this.add('corsPort', corsPort);
this.add('download', download);
this.add('preventSelf', preventSelf);
this.add('preventAll', preventAll);
// Outside of the test suite
this.add('sameUrl', sameUrl, false);
}
public add(name: string, check: PreventCheck, suite: boolean = true): void {
this.tests.set(name, check);
suite && this.suite.push(name);
}
/**
* Run individual test
*/
public run(name: string, el: Link, event: Event, href: string): boolean {
return this.tests.get(name)({
el,
event,
href,
});
}
/**
* Run test suite
*/
public checkLink(el: Link, event: Event, href: string): boolean {
return this.suite.some(name => this.run(name, el, event, href));
}
}
================================================
FILE: packages/core/src/modules/Store.ts
================================================
/**
* @barba/core/modules/store
*
* ## Transitions store.
*
* - Resolve transition
* - Manage rules
*
* @module core/modules/store
* @preferred
*/
/***/
// Definitions
import {
IRule,
IRules,
ITransitionData,
ITransitionFilters,
ITransitionOnce,
ITransitionPage,
RuleName,
} from '../defs';
// Modules
import { Logger } from './Logger';
export class Store {
public logger: Logger = new Logger('@barba/core');
/**
* All registered transitions.
*/
public all: ITransitionPage[] = [];
/**
* "Page only" registered transitions.
*/
public page: ITransitionPage[] = [];
/**
* "Once only" registered transitions.
*/
public once: ITransitionOnce[] = [];
/**
* Rules for transition resolution.
*
* Defaults:
*
* - namespace
* - custom
*/
private _rules: IRule[] = [
{
name: 'namespace',
type: 'strings',
},
{
name: 'custom',
type: 'function',
},
];
/**
* Init store.
*/
constructor(transitions: ITransitionPage[] = []) {
/* istanbul ignore else */
if (transitions) {
// TODO: add check for valid transitions? criteria? (once || enter && leave)
this.all = this.all.concat(transitions);
}
this.update();
}
/**
* Add rule or transition.
*/
public add(type: 'rule' | 'transition', data: any): void {
switch (type) {
case 'rule':
// TODO: check for valid rule
this._rules.splice(data.position || 0, 0, data.value);
break;
case 'transition':
default:
// TODO: check for valid transition
this.all.push(data);
break;
}
this.update();
}
/**
* Resolve transition.
*/
public resolve(
data: ITransitionData,
filters: ITransitionFilters = {}
): ITransitionOnce | ITransitionPage {
// Filter on "once"
let transitions = filters.once ? this.once : this.page;
// Filter on "self"
if (filters.self) {
transitions = transitions.filter(t => t.name && t.name === 'self');
} else {
transitions = transitions.filter(t => !t.name || t.name !== 'self');
}
// All matching transition infos
const matching = new Map();
// Active = first of valid transitions
// sorted by directions (from/to, from || to, …)
const active = transitions.find(t => {
let valid = true;
const match = {};
if (filters.self && t.name === 'self') {
matching.set(t, match);
return true;
}
// Check rules
this._rules.reverse().forEach(rule => {
if (valid) {
valid = this._check(t, rule, data, match);
// From/to check
if (t.from && t.to) {
valid =
this._check(t, rule, data, match, 'from') &&
this._check(t, rule, data, match, 'to');
}
if (t.from && !t.to) {
valid = this._check(t, rule, data, match, 'from');
}
if (!t.from && t.to) {
valid = this._check(t, rule, data, match, 'to');
}
}
});
matching.set(t, match);
return valid;
});
const activeMatch = matching.get(active);
const transitionType = [];
if (filters.once) {
transitionType.push('once');
} else {
transitionType.push('page');
}
if (filters.self) {
transitionType.push('self');
}
if (activeMatch) {
// Log resolved transition
const infos: any[] = [active];
// Log if matching criteria
Object.keys(activeMatch).length > 0 && infos.push(activeMatch);
this.logger.info(
`Transition found [${transitionType.join(',')}]`,
...infos
);
} else {
this.logger.info(`No transition found [${transitionType.join(',')}]`);
}
return active;
}
/**
* ### Update store.
*
* - Reorder transition by priorities
* - Get wait indicator
* - Get once transitions
*/
public update(): void {
// Reorder by priorities
this.all = this.all
.map(t => this._addPriority(t))
.sort((a, b) => a.priority - b.priority)
.reverse()
.map(t => {
delete t.priority;
return t;
});
this.page = this.all.filter(
t => t.leave !== undefined || t.enter !== undefined
) as ITransitionPage[];
this.once = this.all.filter(t => t.once !== undefined) as ITransitionOnce[];
}
/**
* ### Check if transition apply.
*
* Based on rule, page data and optional direction:
*
* 1. transition has no rule "property":
* - always returns true
* 2. transition has rule "property":
* - "strings" should be present on both side (transition + page) and match
* - "function" should return true
*/
private _check(
transition: ITransitionPage,
rule: IRule,
data: ITransitionData,
match: any,
direction?: 'from' | 'to'
): boolean {
let isValid = true;
let hasMatch = false;
const t = transition;
const { name, type } = rule;
const strRule = name as IRules['strings'];
const objRule = name as IRules['object'];
const fnName = name as IRules['function'];
const base = direction ? t[direction] : t; // = t || t.from || t.to
const page = direction === 'to' ? data.next : data.current; // = current || next
const exist = direction ? base && base[name] : base[name];
// If transition rule exists
if (exist) {
switch (type) {
case 'strings':
default: {
// Array support
const names: string[] = Array.isArray(base[strRule])
? (base[strRule] as string[])
: [base[strRule] as string];
// For matching, prop should be present on both sides and match
if (page[strRule] && names.indexOf(page[strRule]) !== -1) {
hasMatch = true;
}
// If transition prop is different from current, not valid
if (names.indexOf(page[strRule]) === -1) {
isValid = false;
}
break;
}
case 'object': {
// Array support
const names: string[] = Array.isArray(base[objRule])
? (base[objRule] as string[])
: [base[objRule] as string];
// For matching, prop should be present on both sides and match
if (page[objRule]) {
if (
page[objRule].name &&
names.indexOf(page[objRule].name) !== -1
) {
hasMatch = true;
}
// If transition prop is different from current, not valid
if (names.indexOf(page[objRule].name) === -1) {
isValid = false;
}
} else {
isValid = false;
}
break;
}
case 'function':
if (base[fnName](data)) {
hasMatch = true;
} else {
isValid = false;
}
break;
}
if (hasMatch) {
if (direction) {
match[direction] = match[direction] || {};
match[direction][name] = t[direction][name];
} else {
match[name] = t[name];
}
}
}
return isValid;
}
/**
* ### Calculate transition priority.
*
* Based on:
*
* - rule "position" (index) give tens, hundreds, thousands, …
* - from/to properties give units (0, 1 or 2)
*/
private _calculatePriority(
t: ITransitionPage,
ruleName: RuleName,
ruleIndex: number
): number {
let priority = 0;
if (
t[ruleName] ||
(t.from && t.from[ruleName]) ||
(t.to && t.to[ruleName])
) {
priority += Math.pow(10, ruleIndex);
if (t.from && t.from[ruleName]) {
priority += 1;
}
if (t.to && t.to[ruleName]) {
priority += 2;
}
}
return priority;
}
private _addPriority(t: ITransitionPage): ITransitionPage {
t.priority = 0;
let priority = 0;
this._rules.forEach((rule, i) => {
const { name } = rule;
const index = i + 1;
priority += this._calculatePriority(t, name, index);
});
t.priority = priority;
return t;
}
}
================================================
FILE: packages/core/src/modules/Transitions.ts
================================================
/**
* @barba/core/modules/transitions
*
* ## Transitions manager.
*
* - Handle hooks and transition lifecycle
*
* @module core/modules/transitions
* @preferred
*/
/***/
// Definitions
import {
HooksTransition,
HooksTransitionMap,
IResponse,
ITransitionData,
ITransitionFilters,
ITransitionOnce,
ITransitionPage,
Wrapper,
} from '../defs';
// Hooks
import { hooks } from '../hooks';
// Utils
import { dom, helpers, runAsync } from '../utils';
// Modules
import { BarbaError } from './Error';
import { Logger } from './Logger';
import { Store } from './Store';
export class Transitions {
public logger: Logger = new Logger('@barba/core');
public store: Store;
private _running: boolean = false;
constructor(transitions: ITransitionPage[] = []) {
this.store = new Store(transitions);
}
/**
* Get resolved transition
*
* - based on data
*/
public get(
data: ITransitionData,
filters?: ITransitionFilters
): ITransitionOnce | ITransitionPage {
return this.store.resolve(data, filters);
}
/**
* Animation running status.
*/
get isRunning(): boolean {
return this._running;
}
set isRunning(status: boolean) {
this._running = status;
}
/**
* Check for registered once transition(s).
*/
get hasOnce(): boolean {
return this.store.once.length > 0;
}
/**
* Check for registered self transition.
*/
get hasSelf(): boolean {
return this.store.all.some(t => t.name === 'self');
}
/**
* ### Wait indicator.
*
* Tells Barba to get next page data
* before starting the resolution
* because some registered transitions need
* next page data to be resolved (eg: `sync: true`, `to: { namespace }`, …)
*/
get shouldWait(): boolean {
return this.store.all.some(t => (t.to && !t.to.route) || t.sync);
}
/**
* ### Do "once" transition.
*
* Hooks: see [[HooksOnce]].
*/
public async doOnce({
data,
transition,
}: {
data: ITransitionData;
transition: ITransitionOnce;
}) {
const t = transition || {};
this._running = true;
try {
await this._doAsyncHook('beforeOnce', data, t);
await this.once(data, t);
await this._doAsyncHook('afterOnce', data, t);
} catch (error) {
this._running = false;
this.logger.debug('Transition error [before/after/once]');
this.logger.error(error);
}
this._running = false;
}
/**
* ### Do "page" transition.
*
* Hooks: see [[HooksPage]].
*
* `sync: false` (default) order:
*
* 1. before
* 2. beforeLeave
* 3. leave
* 4. afterLeave
* 5. beforeEnter
* 6. enter
* 7. afterEnter
* 8. after
*
* `sync: true` order:
*
* 1. before
* 2. beforeLeave
* 3. beforeEnter
* 4. leave & enter
* 5. afterLeave
* 6. afterEnter
* 7. after
*/
public async doPage({
data,
transition,
page,
wrapper,
}: {
data: ITransitionData;
transition: ITransitionPage;
page: Promise;
wrapper: Wrapper;
}) {
const t = transition || {};
const sync = t.sync === true || false;
this._running = true;
try {
// Check sync mode, wait for next content
if (sync) {
await helpers.update(page, data);
}
await this._doAsyncHook('before', data, t);
if (sync) {
try {
await this.add(data, wrapper);
// Before actions
await this._doAsyncHook('beforeLeave', data, t);
await this._doAsyncHook('beforeEnter', data, t);
// Actions
await Promise.all([this.leave(data, t), this.enter(data, t)]);
// After actions
await this._doAsyncHook('afterLeave', data, t);
await this._doAsyncHook('afterEnter', data, t);
} catch (error) {
// this.logger.debug('Transition error [sync]');
// this.logger.error(error);
if (this._isTransitionError(error)) {
throw new BarbaError(
(error as Error),
'Transition error [sync]'
);
}
}
} else {
let leaveResult: any = false;
try {
// Leave
await this._doAsyncHook('beforeLeave', data, t);
leaveResult = await Promise.all([
this.leave(data, t),
helpers.update(page, data),
]).then(values => values[0]);
await this._doAsyncHook('afterLeave', data, t);
// TODO: check here "valid" page result
// before going further
} catch (error) {
// this.logger.debug('Transition error [before/after/leave]');
// this.logger.error(error);
if (this._isTransitionError(error)) {
throw new BarbaError(
(error as Error),
'Transition error [before/after/leave]'
);
}
}
try {
// Enter
/* istanbul ignore else */
if (leaveResult !== false) {
await this.add(data, wrapper);
await this._doAsyncHook('beforeEnter', data, t);
await this.enter(data, t, leaveResult);
await this._doAsyncHook('afterEnter', data, t);
}
} catch (error) {
// this.logger.debug('Transition error [before/after/enter]');
// this.logger.error(error);
if (this._isTransitionError(error)) {
throw new BarbaError(
(error as Error),
'Transition error [before/after/enter]'
);
}
}
}
// Remove current container
await this.remove(data);
await this._doAsyncHook('after', data, t);
} catch (error: any) {
this._running = false;
// If "custom/specific" barba error.
/* istanbul ignore else */
if (error.name && error.name === 'BarbaError') {
this.logger.debug(error.label);
this.logger.error(error.error);
throw error;
}
this.logger.debug('Transition error [page]');
this.logger.error(error);
throw error;
}
this._running = false;
}
/**
* Once hook + async "once" transition.
*/
public async once(data: ITransitionData, t: ITransitionOnce): Promise {
await hooks.do('once', data, t);
return t.once ? runAsync(t.once, t)(data) : Promise.resolve();
}
/**
* Leave hook + async "leave" transition.
*/
public async leave(data: ITransitionData, t: ITransitionPage): Promise {
await hooks.do('leave', data, t);
return t.leave ? runAsync(t.leave, t)(data) : Promise.resolve();
}
/**
* Enter hook + async "enter" transition.
*/
public async enter(
data: ITransitionData,
t: ITransitionPage,
leaveResult?: any
): Promise {
await hooks.do('enter', data, t);
return t.enter
? runAsync(t.enter, t)(data, leaveResult)
: Promise.resolve();
}
/**
* Add next container.
*/
public async add(data: ITransitionData, wrapper: Wrapper): Promise {
dom.addContainer(data.next.container, wrapper);
hooks.do('nextAdded', data);
}
/**
* Remove current container.
*/
public async remove(data: ITransitionData): Promise {
dom.removeContainer(data.current.container);
hooks.do('currentRemoved', data);
}
private _isTransitionError(error: any) {
if (error.message) {
// Errors from request
return !/Timeout error|Fetch error/.test(error.message);
}
if (error.status) {
// Errors from request
return false;
}
return true;
}
/**
* Do hooks + async transition methods.
*/
private async _doAsyncHook(
hook: HooksTransition,
data: ITransitionData,
t: HooksTransitionMap
): Promise {
await hooks.do(hook, data, t);
return t[hook] ? runAsync(t[hook], t)(data) : Promise.resolve();
}
}
================================================
FILE: packages/core/src/modules/Views.ts
================================================
/**
* @barba/core/modules/views
*
* ## Views manager.
*
* @module core/modules/views
* @preferred
*/
/***/
// Definitions
import { HooksView, IView, IViewData } from '../defs';
// Hooks
import { hooks } from '../hooks';
// Utils
import { runAsync } from '../utils';
// Types
type Hook = (data: IViewData) => Promise;
export class Views {
/**
* Available hook names for views.
*/
public names: HooksView[] = [
'beforeLeave',
'afterLeave',
'beforeEnter',
'afterEnter',
];
/**
* Registered views by namespace.
*/
public byNamespace: Map = new Map();
/**
* Init views.
*/
constructor(views: IView[]) {
if (views.length === 0) {
return;
}
// TODO: add check
// for valid views? criteria? (namespace property, string ?)
// or duplicate
views.forEach(view => {
this.byNamespace.set(view.namespace, view);
});
this.names.forEach(name => {
hooks[name](this._createHook(name));
});
}
/**
* Create the hook method.
*
* - get view based on namespace
* - execute callback with transition data
*/
private _createHook(name: HooksView): Hook {
return data => {
const { namespace } = name.match(/enter/i) ? data.next : data.current;
const view = this.byNamespace.get(namespace);
// TODO: manage self…
// if (view && data.trigger !== 'self') {
if (view && view[name]) {
return runAsync(view[name], view)(data);
}
return Promise.resolve();
};
}
}
================================================
FILE: packages/core/src/polyfills/index.ts
================================================
// Element.prototype.matches polyfill
// https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill
if (!Element.prototype.matches) {
Element.prototype.matches =
(Element as any).prototype.msMatchesSelector ||
Element.prototype.webkitMatchesSelector;
}
// Element.prototype.closest polyfill
// https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
if (!Element.prototype.closest) {
Element.prototype.closest = function closest(s: string) {
let el = this;
do {
if (el.matches(s)) {
return el;
}
el = (el.parentElement || el.parentNode) as Element;
} while (el !== null && el.nodeType === 1);
return null;
};
}
================================================
FILE: packages/core/src/schemas/attribute.ts
================================================
/**
* @barba/core/schemas
*