frontitygit
Version:
A Frontity source package for the REST API of self-hosted and WordPress.com sites
175 lines (157 loc) • 4.34 kB
text/typescript
import WpSource from "../../types";
/**
* Add the final slash to a link. It does nothing if the link already has a
* final slash.
*
* @param link - The link to be processed.
*
* @returns The same link but with the final slash.
*/
export const addFinalSlash = (link: string): string =>
link.indexOf('.html') != -1 && link.indexOf('blog') == -1 ? link.replace('.html/','.html') : link.replace(/\/?$/, "/");
/**
* Add the first slash to a link. It does nothing if the link already has a
* leading slash.
*
* @param link - The link to be processed.
*
* @returns The same link but with the leading slash.
*/
export const addLeadingSlash = (link: string): string =>
link.replace(/^\/?/, "/");
/**
* Turn a query string into a query object.
*
* @param queryString - The query, in string format.
*
* @returns An object with the queries and its values.
*/
export const queryToObj = (queryString = ""): Record<string, string> =>
queryString && queryString.includes("=")
? queryString.split("&").reduce((result, param) => {
const [k, v] = param.split("=");
result[k] = v;
return result;
}, {})
: {};
/**
* Turn a query object into a query string.
*
* @param queryObject - The query object.
*
* @returns The query, in string format.
*/
export const objToQuery = (queryObject: Record<string, any>) => {
const entries = Object.entries(queryObject).sort(([a], [b]) => {
if (a < b) return -1;
if (a > b) return 1;
return 0;
});
return entries.length
? `?${entries.map(([key, value]) => `${key}=${value}`).join("&")}`
: "";
};
/**
* Concatenate links together, making sure there are no double slashes.
*
* @param links - The links to be concatenated.
*
* @returns The final link.
*/
export const concatLink = (...links: string[]) =>
[""]
.concat(...links.map((path) => path.split("/").filter((p) => p)), "")
.join("/");
/**
* The return of the {@link extractLinkParts} function.
*/
interface ExtractLinkPartsReturn {
/**
* The pathname of the link.
*/
pathname: string;
/**
* The query string of the link.
*/
queryString: string;
/**
* The hash part of the link.
*/
hash: string;
}
/**
* Extract the different link parts: pathname, query and hash.
*
* @param link - The link.
*
* @returns An object with the different parts of the link. Defined in {@link
* ExtractLinkPartsReturn}.
*/
export const extractLinkParts = (link: string): ExtractLinkPartsReturn => {
const [
,
pathname,
queryString,
hash,
] = /^(?:(?:[^:/?#]+):)?(?:\/\/(?:[^/?#]*))?([^?#]*)(?:\?([^#]*))?(#.*)?/.exec(
link
);
return { pathname, queryString, hash };
};
/**
* Extract the different Frontity link params.
*
* @param link - The link.
*
* @returns The link params, defined by {@link LinkParams}.
*/
export const parse: WpSource["libraries"]["source"]["parse"] = (link) => {
const { pathname, queryString, hash } = extractLinkParts(link);
const [, path, page] = /^(.*)page\/(\d+)\/?(\?.*)?$/.exec(pathname) || [
null,
pathname,
"1",
];
return {
path: addFinalSlash(path),
route: addFinalSlash(path),
page: parseInt(page, 10),
query: queryToObj(queryString),
queryString: objToQuery(queryToObj(queryString)),
hash,
};
};
/**
* Turn a set of Frontity link params into a string link.
*
* @param linkParams - The link params, defined by {@link LinkParams}.
*
* @returns The link, in string format.
*/
export const stringify: WpSource["libraries"]["source"]["stringify"] = ({
path = "/",
route,
page = 1,
query = {},
hash = "",
}) => {
// Use route if present, otherwise use path.
route = route || path;
// Correct the route.
route = addFinalSlash(route);
const pathAndPage = page > 1 ? `${route}page/${page}/` : route;
const queryString = objToQuery(query);
return `${pathAndPage.toLowerCase()}${queryString}${hash}`;
};
/**
* Normalize a link, making sure that multiple links that should point to
* the same canonical link are processed as a single one.
*
* @example `/some-post -> /some-post/`
*
* @param link - The link to be normalized.
*
* @returns The normalized link.
*/
export const normalize = (link: string): string => stringify(parse(link));
export default { parse, stringify, normalize };