/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at . */
// @flow
import { parse } from "../../utils/url";
import type { TreeNode, TreeSource, TreeDirectory, ParentMap } from "./types";
import type { Source } from "../../types";
import { isPretty } from "../source";
import { getURL } from "./getURL";
const IGNORED_URLS = ["debugger eval code", "XStringBundle"];
export function nodeHasChildren(item: TreeNode): boolean {
return Array.isArray(item.contents) && item.type == "directory";
}
export function isExactUrlMatch(pathPart: string, debuggeeUrl: string) {
// compare to hostname with an optional 'www.' prefix
const { host } = parse(debuggeeUrl);
if (!host) {
return false;
}
return host.replace(/^www\./, "") === pathPart.replace(/^www\./, "");
}
export function isPathDirectory(path: string) {
// Assume that all urls point to files except when they end with '/'
// Or directory node has children
const parts = path.split("/").filter(p => p !== "");
return parts.length === 0 || path.slice(-1) === "/";
}
export function isDirectory(item: TreeNode) {
return (
(isPathDirectory(item.path) || item.type === "directory") &&
item.name != "(index)"
);
}
export function getSourceFromNode(item: TreeNode): ?Source {
const { contents } = item;
if (!isDirectory(item) && !Array.isArray(contents)) {
return contents;
}
}
export function isSource(item: TreeNode) {
return item.type === "source";
}
export function getFileExtension(source: Source): string {
const parsedUrl = getURL(source).path;
if (!parsedUrl) {
return "";
}
return parsedUrl.split(".").pop();
}
export function isNotJavaScript(source: Source): boolean {
return ["css", "svg", "png"].includes(getFileExtension(source));
}
export function isInvalidUrl(url: Object, source: Source) {
return (
IGNORED_URLS.includes(url) ||
!source.url ||
!url.group ||
isPretty(source) ||
isNotJavaScript(source)
);
}
export function partIsFile(index: number, parts: Array, url: Object) {
const isLastPart = index === parts.length - 1;
return !isDirectory(url) && isLastPart;
}
export function createDirectoryNode(
name: string,
path: string,
contents: TreeNode[]
): TreeDirectory {
return {
type: "directory",
name,
path,
contents
};
}
export function createSourceNode(
name: string,
path: string,
contents: Source
): TreeSource {
return {
type: "source",
name,
path,
contents
};
}
export function createParentMap(tree: TreeNode): ParentMap {
const map = new WeakMap();
function _traverse(subtree) {
if (subtree.type === "directory") {
for (const child of subtree.contents) {
map.set(child, subtree);
_traverse(child);
}
}
}
if (tree.type === "directory") {
// Don't link each top-level path to the "root" node because the
// user never sees the root
tree.contents.forEach(_traverse);
}
return map;
}
export function getRelativePath(url: string) {
const { pathname } = parse(url);
if (!pathname) {
return url;
}
const path = pathname.split("/");
path.shift();
return path.join("/");
}