Skip to content

Commit

Permalink
Merge pull request #9 from BRIXTOL/next
Browse files Browse the repository at this point in the history
v0.3.0-beta.1
  • Loading branch information
panoply authored Dec 22, 2021
2 parents 834050c + 3709636 commit cfeb8a2
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 80 deletions.
8 changes: 6 additions & 2 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# CHANGELOG

### 18/12/2012
### 21/12/2012 | v0.3.0-beta.1

##### Internal Improvements

Expand All @@ -16,7 +16,7 @@ This is a new render method that will override defined `targets` which is helpfu

This version provides a preemptive fetches. There are 2 additions exposed in the version, which need a little more work but can be used. A new options for **reverse** caching is available which will execute a preemptive fetch of the previous page in the history stack when no snapshot exists in cache. Snapshot cache is purged if a browser refresh occurs and when navigating backwards or pages will need to be re-fetched resulting in minor delays if a refresh was triggered between browsing. By default, the last known previous page in the history stack is now fetched.

In addition to the reverse cache feature, a **preemptive** option is now available to the `prefetch` config. This option currently accepts a string list of paths only. Values defined here will be fetched preemptively and saved to cache either upon initial load anf those pages will be visited in background asynchronously in the order they were passed. In the next release preemptive fetches will be made possible according to a specific path.
In addition to the reverse cache feature, a **preemptive** option is now available to the `prefetch` config. This option currently accepts a string list of paths only. Values defined here will be fetched preemptively and saved to cache either upon initial load and those pages will be visited in background asynchronously in the order they were passed. In the next release preemptive fetches will be made possible according to a specific path.

##### Methods

Expand All @@ -33,6 +33,10 @@ Below is a the complete list of changes applied in this release
- Fixed scroll position preservation between no-cached navigations
- Promise methods resolve page state correctly.
- Improved `<head>` node replacements between navigations.
- Replaced how fragments are replaced between visits.
- Added a hydration support for partial replacements
- Overhauled the store engine
- Clean up various other areas.

#### 10/08/2021 | v0.2.0-beta.1

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@brixtol/pjax",
"version": "0.2.0-beta.1",
"version": "0.3.0-beta.1",
"private": false,
"description": "A modern next generation pjax solution for SSR web applications",
"author": "ΝΙΚΟΛΑΣ ΣΑΒΒΙΔΗΣ",
Expand Down
13 changes: 9 additions & 4 deletions src/app/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { isArray } from '../constants/native';
import { connect } from './connects';
import * as store from './store';
import { forEach } from './utils';
import { ILocation } from '../types/location';

/**
* Sets initial page state executing on intial load.
Expand All @@ -31,12 +32,16 @@ function onload (): void {
}

if (store.config.cache.reverse) {
const previous = browser.location.state.location;
if (previous.lastpath) request.get(previous.lastpath, 'reverse');
const previous: { location?: ILocation } = browser.location.state;
if (previous?.location?.lastpath) {
request.get(previous.location.lastpath, 'reverse').then(() => {
browser.replace(window.location, page);
});
}
} else {
browser.replace(window.location, page);
}

browser.replace(window.location, page);

removeEventListener('load', onload);

}
Expand Down
21 changes: 15 additions & 6 deletions src/app/object.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import merge from 'mergerino';
import { assign, defineProperty, getOwnPropertyNames, create } from '../constants/native';
import {
defineProperty,
getOwnPropertyNames,
create
} from '../constants/native';

/**
* Object
Expand All @@ -10,7 +14,7 @@ import { assign, defineProperty, getOwnPropertyNames, create } from '../constant
*/
export function object <T> ({
writable,
configurable = true,
configurable,
enumerable
}: Omit<PropertyDescriptor, 'value'> = {
writable: false,
Expand Down Expand Up @@ -68,7 +72,9 @@ export function object <T> ({
*/
update <K extends keyof T> (prop: K, ...value: T[K][]): T[K] {

return assign(o[prop], merge(o[prop] as any, ...value));
o[prop] = merge(o[prop] || {} as any, value);

return o[prop];

},

Expand Down Expand Up @@ -109,13 +115,16 @@ export function object <T> ({
* will only clear that specific record. Returns
* boolean when sucessful clear is executed.
*/
clear (exclude: string[] = []): boolean {
clear (exclude: string[] = []): any[] {

const snapshots = [];

getOwnPropertyNames(o).forEach(url => {
if (exclude.indexOf(url) !== -1) delete o[url];
if (!exclude.includes(url)) delete o[url];
else snapshots.push(o[url].snapshot);
});

return true;
return snapshots;

}

Expand Down
86 changes: 44 additions & 42 deletions src/app/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { dispatchEvent } from './events';
import { progress } from './progress';
import { IPage } from '../types/page';
import history from 'history/browser';
import { from, is } from '../constants/native';
import { from } from '../constants/native';
import * as store from './store';
import * as mouseover from '../observers/hover';
import * as intersect from '../observers/intersect';
Expand Down Expand Up @@ -134,29 +134,6 @@ function appendTrackedNode (node: Element): void {

}

/**
* Apply actions to the documents target fragments
* with the request response.
*/
function replaceTarget (target: Element, state: IPage): (DOM: Element) => void {

return DOM => {

if (dispatchEvent('pjax:render', { target }, true)) {

DOM.innerHTML = target.innerHTML;

if (state.append || state.prepend) {
const fragment = document.createElement('div');
forEach(fragment.appendChild)(from(target.childNodes));
if (state.append) DOM.appendChild(fragment);
else DOM.insertBefore(fragment, DOM.firstChild);
}
}

};
}

/**
* Parse HTML document string from request response
* using `parser()` method. Cached pages will pass
Expand Down Expand Up @@ -184,17 +161,47 @@ export async function capture (state: IPage) {
}
}

function renderNodes (state: IPage, target: Document, nodes: string[]) {
function renderNodes (state: IPage, target: Document) {

const nodes = state.replace ? [ ...state.targets, ...state.replace ] : state.targets;
const selector = nodes.join(',');
const current = document.body.querySelectorAll(selector);

if (current.length === 0) return document.body.replaceWith(target.body);

const fetched = target.body.querySelectorAll(selector);

let fallback = 1;
current.forEach((node, i) => {

forEach(element => {
const node = target.body.querySelector(element);
if (node) forEach(replaceTarget(node, state))(document.body.querySelectorAll(element));
else fallback++;
}, nodes);
if (!node.matches(nodes[i])) return;
if (!dispatchEvent('pjax:render', { target: nodes[i] }, true)) return;

if (is(fallback, state.targets.length)) replaceTarget(target.body, state)(document.body);
node.replaceWith(fetched[i]);

if (state.append || state.prepend) {

const fragment = document.createElement('div');
target.childNodes.forEach(fragment.appendChild);

return state.append
? node.appendChild(fragment)
: node.insertBefore(fragment, node.firstChild);

}

});

}

function hydrateNodes (target: Document, selectors: string[]) {

const nodes = selectors.join(',');
const current = document.body.querySelectorAll(nodes);

if (current.length > 0) {
const fetched = target.body.querySelectorAll(nodes);
current.forEach((node, i) => node.replaceWith(fetched[i]));
}

}

Expand Down Expand Up @@ -229,21 +236,16 @@ export function update (state: IPage, popstate?: boolean): IPage {

if (state.hydrate) {

renderNodes(state, target, state.hydrate);

const capture = { ...state, hydrate: undefined };
store.clear();
hydrateNodes(target, state.hydrate);

const page = store.capture(capture, document.documentElement.outerHTML);
const { url } = store.pages.update(state.url, { hydrate: undefined });
store.snaps.clear(store.pages.clear([ url ]));

history.replace(capture.location, page);
console.log(store.pages.all);

} else {

renderNodes(state, target, state.replace ? [
...state.targets,
...state.replace
] : state.targets);
renderNodes(state, target);

target.body.querySelectorAll('[data-pjax-track]').forEach(appendTrackedNode);

Expand Down
19 changes: 12 additions & 7 deletions src/app/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { nanoid } from 'nanoid';
import { object } from './object';
import { IPage } from '../types/page';
import { IOptions } from '../types/options';
import { assign } from '../constants/native';
import { assign, isArray } from '../constants/native';
import { dispatchEvent } from './events';
import * as scroll from '../observers/scroll';
import * as progress from './progress';
Expand Down Expand Up @@ -150,17 +150,22 @@ export function hydrate (state: IPage, snapshot: string): IPage {
* Removes cached records. Optionally pass in URL
* to remove specific record.
*/
export function clear (url?: string): void {
export function clear (url?: string[] | string): void {

if (typeof url === 'string') {
if (typeof url === 'undefined') {

pages.clear();
snaps.clear();

} else if (typeof url === 'string') {

snaps.delete(pages.get(url).snapshot);
pages.delete(url);

} else {
} else if (isArray(url)) {

pages.clear();
snaps.clear();
const saved = pages.clear(url);
snaps.clear(saved as any);

}

Expand Down Expand Up @@ -201,5 +206,5 @@ export function history (): string {

browser.replace(location, updated);

return location.state.url;
return (location.state as any).url;
}
1 change: 1 addition & 0 deletions src/constants/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const {
assign,
is,
keys,
values,
defineProperty,
getOwnPropertyNames
} = Object;
Expand Down
7 changes: 2 additions & 5 deletions src/observers/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,9 @@ export function stop (): void {
*/
export function updateState (): IPage {

const { location } = browser;
const updated = merge(location.state, { position });
const updated = merge(browser.location.state as IPage, { position });

console.log(location);

browser.replace(location, updated);
browser.replace(browser.location, updated);

return updated;

Expand Down
28 changes: 15 additions & 13 deletions src/observers/hrefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,25 +70,27 @@ function handleTrigger (event: MouseEvent): void {
const target = getLink(event.target, 'a:not([data-pjax-disable]):not([href^="#"])');

if (!target) return undefined;
if (!dispatchEvent('pjax:trigger', { target }, true)) return undefined;

const { url, location } = path.get(target, true);
const click = handleClick(target);
if (dispatchEvent('pjax:trigger', { target }, true)) {

if (request.transit.has(url)) {
const { url, location } = path.get(target, true);
const click = handleClick(target);

target.addEventListener('click', click(url), false);
if (request.transit.has(url)) {

} else {

const state = attrparse(target, { url, location, position: y0x0() });
target.addEventListener('click', click(url), false);

if (store.has(url)) {
const page = store.pages.update(state.url, state);
target.addEventListener('click', click(page), false);
} else {
request.get(state); // TRIGGERS FETCH
target.addEventListener('click', click(url), false);

const state = attrparse(target, { url, location, position: y0x0() });

if (store.has(url)) {
const page = store.pages.update(state.url, state);
target.addEventListener('click', click(page), false);
} else {
request.get(state); // TRIGGERS FETCH
target.addEventListener('click', click(url), false);
}
}
}
}
Expand Down

0 comments on commit cfeb8a2

Please sign in to comment.