Skip to content

Commit

Permalink
Merge pull request #13 from swup/typescript
Browse files Browse the repository at this point in the history
Port to TypeScript
  • Loading branch information
daun authored Aug 9, 2023
2 parents 0ba4404 + 1f28c12 commit c7b4a2f
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 19 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

<!-- ## [Unreleased] -->

## [4.1.0] - 2023-08-09

- Port to TypeScript

## [4.0.0] - 2023-07-26

- Update for swup 4 compatibility
Expand Down Expand Up @@ -30,8 +34,9 @@

- Initial release

[Unreleased]: https://github.com/swup/route-name-plugin/compare/4.0.0...HEAD
[Unreleased]: https://github.com/swup/route-name-plugin/compare/4.1.0...HEAD

[4.1.0]: https://github.com/swup/route-name-plugin/releases/tag/4.1.0
[4.0.0]: https://github.com/swup/route-name-plugin/releases/tag/4.0.0
[3.0.2]: https://github.com/swup/route-name-plugin/releases/tag/3.0.2
[3.0.1]: https://github.com/swup/route-name-plugin/releases/tag/3.0.1
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 10 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
{
"name": "@swup/route-name-plugin",
"amdName": "SwupRouteNamePlugin",
"version": "4.0.0",
"version": "4.1.0",
"description": "A swup plugin for named routes and route-based animation classes",
"type": "module",
"source": "src/index.js",
"source": "src/index.ts",
"main": "./dist/index.cjs",
"module": "./dist/index.module.js",
"exports": "./dist/index.modern.js",
"unpkg": "./dist/index.umd.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.modern.js",
"require": "./dist/index.cjs"
}
},
"files": [
"dist"
],
Expand Down
68 changes: 55 additions & 13 deletions src/index.js → src/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,60 @@
import Plugin from '@swup/plugin';
import { classify, getCurrentUrl, matchPath, updateHistoryRecord } from 'swup';
import type { Visit } from 'swup';

declare module 'swup' {
export interface VisitFrom {
/** Identified route name */
route?: string;
}
export interface VisitTo {
/** Identified route name */
route?: string;
}
}

type Route = {
/** The name of the route. */
name: string;
/** The path pattern to match the URL against. */
path: string;
};

type CompiledRoute = Route & {
/** Match function to check if the pattern matches a given URL */
matches: MatchFunction;
};

type MatchOptions = Parameters<typeof matchPath>[1];
type MatchFunction = ReturnType<typeof matchPath>;

type Options = {
/** Array of patterns for identifying named routes. */
routes: Route[];
/** Default route name if no match was found. */
unknownRoute: string;
/** Options for matching paths. Directly passed into `path-to-regexp`. */
matchOptions: MatchOptions;
/** Add classnames for raw URLs. */
paths: boolean;
};

export default class SwupRouteNamePlugin extends Plugin {
name = 'SwupRouteNamePlugin';

requires = { swup: '>=4' };

defaults = {
defaults: Options = {
routes: [],
unknownRoute: 'unknown',
matchOptions: {},
paths: false
};
options: Options;

routes: CompiledRoute[];

constructor(options = {}) {
constructor(options: Partial<Options> = {}) {
super();
this.options = { ...this.defaults, ...options };
this.routes = this.compileRoutePatterns();
Expand All @@ -40,29 +81,30 @@ export default class SwupRouteNamePlugin extends Plugin {
});
}

sanitizeRouteName(name) {
sanitizeRouteName(name: string): string {
return name.replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~\s]/g, '');
}

// Get route name for any path
getRouteName(path) {
getRouteName(path: string): string | undefined {
const { name } = this.routes.find((route) => route.matches(path)) || {};
return name || null;
return name || undefined;
}

// Get path name for any path
getPathName(path) {
getPathName(path: string) {
return classify(path) || 'homepage';
}

// Add a `route` key to the visit object's `from` and `to` properties
addRouteKey(visit) {
addRouteKey(visit: Visit) {
if (!this.options.routes.length) {
return;
}

visit.from.route = this.getRouteName(visit.from.url);
visit.to.route = this.getRouteName(visit.to.url);
visit.to.route = this.getRouteName(visit.to.url!);
const unknown = this.options.unknownRoute;

this.swup.log(
`Route: '${visit.from.route || unknown || '(unknown)'}'` +
Expand All @@ -71,7 +113,7 @@ export default class SwupRouteNamePlugin extends Plugin {
}

// Add `from-route-*` and `to-route-*` classnames to html tag
addRouteClasses(visit) {
addRouteClasses(visit: Visit) {
if (!this.options.routes.length) {
return;
}
Expand All @@ -92,27 +134,27 @@ export default class SwupRouteNamePlugin extends Plugin {
}

// Add `from-*` and `to-*` classnames for slugified path
addPathClasses(visit) {
addPathClasses(visit: Visit) {
if (!this.options.paths) {
return;
}

const from = this.getPathName(visit.from.url);
const to = this.getPathName(visit.to.url);
const to = this.getPathName(visit.to.url!);

document.documentElement.classList.add(`from-${from}`);
document.documentElement.classList.add(`to-${to}`);
}

// Remove `from-*` and `from-route-*` classnames from html tag
// Note: swup removes `to-*` classnames on its own already
removeClasses = () => {
removeClasses() {
const htmlClasses = document.documentElement.className.split(' ');
const removeClasses = htmlClasses.filter((classItem) => classItem.startsWith('from-'));
document.documentElement.classList.remove(...removeClasses);
}

updateHistory(visit) {
updateHistory(visit: Visit) {
updateHistoryRecord(undefined, { route: visit.to.route });
}
}
14 changes: 14 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"include": ["src"],
"compilerOptions": {
"target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"moduleResolution": "Node16", /* Specify how TypeScript looks up a file from a given module specifier. */
"rootDirs": ["./src"], /* Allow multiple folders to be treated as one when resolving modules. */
"resolveJsonModule": true, /* Enable importing .json files. */
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
"outDir": "./dist", /* Specify an output folder for all emitted files. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": true /* Enable error reporting for expressions and declarations with an implied 'any' type. */
}
}

0 comments on commit c7b4a2f

Please sign in to comment.