ignore dist/
This commit is contained in:
parent
a3579a4ff1
commit
6b08ab4c80
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
|
|
||||||
|
dist/
|
||||||
|
187
dist/bundle.js
vendored
187
dist/bundle.js
vendored
@ -1,187 +0,0 @@
|
|||||||
// src/index.ts
|
|
||||||
async function githubTree(name, ref) {
|
|
||||||
return {
|
|
||||||
id: 0,
|
|
||||||
path: "",
|
|
||||||
filename: name,
|
|
||||||
kind: {
|
|
||||||
type: "dir",
|
|
||||||
children: await githubListRecursive(name, ref)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async function githubListRecursive(name, ref, path = "", nextId = [1]) {
|
|
||||||
const fileNodes = await fetch(
|
|
||||||
`https://api.github.com/repos/${name}/contents${path}?ref=${ref}`
|
|
||||||
).then((res) => res.json());
|
|
||||||
return Promise.all(
|
|
||||||
fileNodes.map(async (node) => {
|
|
||||||
const id = nextId[0]++;
|
|
||||||
if (node.type === "dir") {
|
|
||||||
return await githubListRecursive(
|
|
||||||
name,
|
|
||||||
ref,
|
|
||||||
`${path}/${node.name}`,
|
|
||||||
nextId
|
|
||||||
).then((children) => ({
|
|
||||||
id,
|
|
||||||
filename: node.name,
|
|
||||||
path,
|
|
||||||
kind: { type: "dir", children }
|
|
||||||
}));
|
|
||||||
} else if (node.type === "file") {
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
filename: node.name,
|
|
||||||
path,
|
|
||||||
kind: { type: "file", url: node.download_url }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
throw new Error();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
function generateTreeHtml(node) {
|
|
||||||
return `<ul>${generateNodeHtml(node)}</ul>`;
|
|
||||||
}
|
|
||||||
function generateNodeHtml(node) {
|
|
||||||
if (node.kind.type === "dir") {
|
|
||||||
const children = node.kind.children.map((node2) => generateNodeHtml(node2)).join("");
|
|
||||||
return `<li>
|
|
||||||
<input type="checkbox" id="checkbox-${node.id}" checked>
|
|
||||||
${node.filename}/
|
|
||||||
<ul>${children}</ul>
|
|
||||||
</li>`;
|
|
||||||
} else if (node.kind.type === "file") {
|
|
||||||
return `
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="checkbox-${node.id}" checked>
|
|
||||||
${node.filename}
|
|
||||||
</li>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
throw new Error();
|
|
||||||
}
|
|
||||||
function queryHtmlINodes(tree) {
|
|
||||||
const nodes = /* @__PURE__ */ new Map();
|
|
||||||
queryHtmlINodesRecursive(nodes, tree);
|
|
||||||
return nodes;
|
|
||||||
}
|
|
||||||
function queryHtmlINodesRecursive(nodes, node, parentId) {
|
|
||||||
const checkbox = document.querySelector(`#checkbox-${node.id}`);
|
|
||||||
if (node.kind.type === "dir") {
|
|
||||||
nodes.set(node.id, { node, parentId, checkbox });
|
|
||||||
for (const child of node.kind.children) {
|
|
||||||
queryHtmlINodesRecursive(nodes, child, node.id);
|
|
||||||
}
|
|
||||||
} else if (node.kind.type === "file") {
|
|
||||||
nodes.set(node.id, { node, parentId, checkbox });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function hydrateHtmlTree(tree) {
|
|
||||||
for (const node of tree.values()) {
|
|
||||||
node.checkbox.addEventListener("change", () => {
|
|
||||||
if (node.node.kind.type === "dir") {
|
|
||||||
setCheckChildrenRecursively(
|
|
||||||
tree,
|
|
||||||
node.node.id,
|
|
||||||
node.checkbox.checked
|
|
||||||
);
|
|
||||||
}
|
|
||||||
checkParentDirCheckRecursively(tree, node.parentId);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function setCheckChildrenRecursively(tree, id, state) {
|
|
||||||
const node = tree.get(id);
|
|
||||||
if (node.node.kind.type !== "dir") {
|
|
||||||
throw new Error();
|
|
||||||
}
|
|
||||||
for (const { id: childId } of node.node.kind.children) {
|
|
||||||
const child = tree.get(childId);
|
|
||||||
child.checkbox.checked = state;
|
|
||||||
if (child.node.kind.type === "dir") {
|
|
||||||
setCheckChildrenRecursively(tree, childId, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function checkParentDirCheckRecursively(tree, parentId) {
|
|
||||||
if (parentId === void 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const parent = tree.get(parentId);
|
|
||||||
if (parent === void 0) {
|
|
||||||
throw new Error();
|
|
||||||
}
|
|
||||||
if (parent.node.kind.type !== "dir") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const checked = parent.node.kind.children.some(({ id }) => tree.get(id).checkbox.checked);
|
|
||||||
parent.checkbox.checked = checked;
|
|
||||||
checkParentDirCheckRecursively(tree, parent.parentId);
|
|
||||||
}
|
|
||||||
async function* searchTree(tree, pattern) {
|
|
||||||
for (const node of tree.values()) {
|
|
||||||
if (node.node.kind.type !== "file") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!node.checkbox.checked) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const text = await fetch(node.node.kind.url).then((res) => res.text());
|
|
||||||
const lines = text.split("\n").map((v, i) => [v, i]);
|
|
||||||
for (const [linetext, i] of lines) {
|
|
||||||
if (!pattern.test(linetext)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const { filename, path } = node.node;
|
|
||||||
const linenr = i + 1;
|
|
||||||
yield { filename, path, linetext, linenr };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var repoNameInput = document.querySelector("#repo-name");
|
|
||||||
var repoRefInput = document.querySelector("#repo-ref");
|
|
||||||
var gitProviderSelect = document.querySelector("#git-provider");
|
|
||||||
var loadRepoButton = document.querySelector("#load-repo");
|
|
||||||
var fileTreeDiv = document.querySelector("#file-tree");
|
|
||||||
var searchPatternInput = document.querySelector("#search-pattern");
|
|
||||||
var searchButton = document.querySelector("#search");
|
|
||||||
var searchStatusSpan = document.querySelector("#search-status");
|
|
||||||
var searchResultsDiv = document.querySelector("#search-results");
|
|
||||||
loadRepoButton.onclick = async () => {
|
|
||||||
const name = repoNameInput.value;
|
|
||||||
const ref = repoRefInput.value;
|
|
||||||
const provider = gitProviderSelect.value;
|
|
||||||
if (provider === "github") {
|
|
||||||
const tree = await githubTree(name, ref);
|
|
||||||
fileTreeDiv.innerHTML = generateTreeHtml(tree);
|
|
||||||
const htmlTree = queryHtmlINodes(tree);
|
|
||||||
hydrateHtmlTree(htmlTree);
|
|
||||||
searchStatusSpan.innerText = ``;
|
|
||||||
searchButton.onclick = async () => {
|
|
||||||
const patternText = searchPatternInput.value;
|
|
||||||
const pattern = new RegExp(patternText);
|
|
||||||
searchStatusSpan.innerText = "Searching ...";
|
|
||||||
searchResultsDiv.innerHTML = "";
|
|
||||||
let matches = 0;
|
|
||||||
for await (const match of searchTree(htmlTree, pattern)) {
|
|
||||||
matches += 1;
|
|
||||||
searchResultsDiv.innerHTML += `
|
|
||||||
<div>
|
|
||||||
<p>${match.path}/${match.filename} line ${match.linenr}</p>
|
|
||||||
<code>${match.linetext}</code>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
if (matches === 0) {
|
|
||||||
searchStatusSpan.innerText = "** Nothing found **";
|
|
||||||
} else {
|
|
||||||
searchStatusSpan.innerText = `\u22C6\u02D9\u27E1 Done, ${matches} matches \u27E1\u02D9\u22C6`;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
searchButton.onclick = () => {
|
|
||||||
searchStatusSpan.innerText = `No repository loaded :(`;
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user