Skip to content

Commit

Permalink
feat: merge ts files
Browse files Browse the repository at this point in the history
  • Loading branch information
alexiscolin committed Dec 7, 2024
1 parent 45276d6 commit 58d9efc
Show file tree
Hide file tree
Showing 12 changed files with 309 additions and 191 deletions.
3 changes: 1 addition & 2 deletions gno.land/pkg/gnoweb/components/help.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<main class="w-full grow-[2] bg-gray-50">
<section class="max-w-screen-max mx-auto px-10 grid grid-cols-10 grid-flow-dense gap-8 xxl:gap-20 items-start min-h-full">
<aside id="sidebar" class="relative h-full" aria-label="Index">
<div class="sticky top-16">
<div class="sticky top-16 pt-0.5">
<div id="sidebar-summary" class="toc h-screen overflow-scroll no-scrollbar">
<span class="block text-gray-300 font-semibold mt-10">Functions Index</span>

Expand Down Expand Up @@ -115,5 +115,4 @@ gnokey broadcast -remote "{{ $.Remote }}" call.tx</span></code></pre>
</section>
</section>
</main>
<script src="/public/js/realmhelp.js"></script>
{{ end }}
3 changes: 1 addition & 2 deletions gno.land/pkg/gnoweb/components/index.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,7 @@
</div>
</nav>
</footer>
<script src="/public/js/searchbar.js"></script>
<script src="/public/js/copy.js"></script>
<script type="module" src="/public/js/index.js"></script>
{{- if .Analytics -}} {{- template "analytics" }} {{- end -}}

{{- end }}
Expand Down
8 changes: 4 additions & 4 deletions gno.land/pkg/gnoweb/components/source.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<main class="w-full grow-[2] bg-gray-50">
<section class="max-w-screen-max mx-auto px-10 grid grid-cols-10 grid-flow-dense gap-8 xxl:gap-20 items-start">
<aside id="sidebar" class="relative h-full" aria-label="Table of Contents">
<div class="sticky top-16">
<div class="sticky top-16 pt-0.5">
<div id="sidebar-summary" class="toc overflow-scroll no-scrollbar">
<span class="block text-gray-300 font-semibold mt-10">Sources Files list</span>
<nav class="text-100 font-mono pb-28">
Expand All @@ -28,11 +28,11 @@
<div class="flex justify-between mb-3">
<div class="flex items-center gap-8">
<h1 class="text-600 font-bold">{{ .FileName }}</h1>
<span class="text-gray-300">{{ .FileSize }} · {{ .FileLines }} lines</span>
<span class="text-gray-300 pt-0.5">{{ .FileSize }} · {{ .FileLines }} lines</span>
</div>
<div class="flex gap-4 text-gray-300">
<button class="flex items-center gap-1 hover:text-gray-600" data-copy-btn="source-code">
<svg class="w-5 h-5 xxl:w-4 xxl:h-4 shrink-0 inline-block xl:hidden xxl:inline-block text-gray-200" data-copy-icon>
<button class="flex items-center gap-1 hover:text-gray-600 pt-0.5" data-copy-btn="source-code">
<svg class="w-5 h-5 xxl:w-4 xxl:h-4 shrink-0 inline-block text-gray-200" data-copy-icon>
<use href="#ico-copy"></use>
<use href="#ico-check" class="hidden"></use>
</svg>
Expand Down
133 changes: 79 additions & 54 deletions gno.land/pkg/gnoweb/frontend/js/copy.ts
Original file line number Diff line number Diff line change
@@ -1,76 +1,101 @@
(() => {
class Copy {
private DOM: {
el: HTMLElement | null;
};
btnClicked: HTMLElement | null = null;
btnClickedIcons: HTMLElement[] = [];
class Copy {
private DOM: {
el: HTMLElement | null;
};
private static FEEDBACK_DELAY = 1500;

constructor() {
this.DOM = {
el: document.querySelector("main"),
};
private btnClicked: HTMLElement | null = null;
private btnClickedIcons: HTMLElement[] = [];

if (this.DOM.el) this.init();
}
private static SELECTORS = {
button: "[data-copy-btn]",
icon: `[data-copy-icon] > use`,
content: (id: string) => `[data-copy-content="${id}"]`,
};

private init() {
this.bindEvents();
}
constructor() {
this.DOM = {
el: document.querySelector<HTMLElement>("main"),
};

private bindEvents() {
this.DOM.el?.addEventListener("click", this.handleClick.bind(this));
if (this.DOM.el) {
this.init();
} else {
console.warn("Copy: Main container not found.");
}
}

private handleClick(event: Event) {
const target = event.target as HTMLElement;
const button = target.closest<HTMLElement>("[data-copy-btn]");
private init(): void {
this.bindEvents();
}

if (!button) return;
private bindEvents(): void {
this.DOM.el?.addEventListener("click", this.handleClick.bind(this));
}

this.btnClicked = button;
this.btnClickedIcons = Array.from(button.querySelectorAll<HTMLElement>(`[data-copy-icon] > use`));
private handleClick(event: Event): void {
const target = event.target as HTMLElement;
const button = target.closest<HTMLElement>(Copy.SELECTORS.button);

const contentId = button.getAttribute("data-copy-btn");
if (!contentId) return;
if (!button) return;

const codeBlock = this.DOM.el?.querySelector<HTMLElement>(`[data-copy-content="${contentId}"]`);
if (codeBlock) this.copyToClipboard(codeBlock);
}
this.btnClicked = button;
this.btnClickedIcons = Array.from(button.querySelectorAll<HTMLElement>(Copy.SELECTORS.icon));

private sanitizeContent(codeBlock: HTMLElement): string {
const html = codeBlock.innerHTML.replace(/<span class="chroma-ln">.*?<\/span>/g, "");
const tempDiv = document.createElement("div");
tempDiv.innerHTML = html;
return tempDiv.textContent?.trim() || "";
const contentId = button.getAttribute("data-copy-btn");
if (!contentId) {
console.warn("Copy: No content ID found on the button.");
return;
}

private toggleIcons() {
this.btnClickedIcons.forEach((icon) => {
icon.classList.toggle("hidden");
});
const codeBlock = this.DOM.el?.querySelector<HTMLElement>(Copy.SELECTORS.content(contentId));
if (codeBlock) {
this.copyToClipboard(codeBlock);
} else {
console.warn(`Copy: No content found for ID "${contentId}".`);
}
}

private sanitizeContent(codeBlock: HTMLElement): string {
const html = codeBlock.innerHTML.replace(/<span class="chroma-ln">.*?<\/span>/g, "");
const tempDiv = document.createElement("div");
tempDiv.innerHTML = html;
return tempDiv.textContent?.trim() || "";
}

private toggleIcons(): void {
this.btnClickedIcons.forEach((icon) => {
icon.classList.toggle("hidden");
});
}

private showFeedback() {
if (!this.btnClicked) return;
private showFeedback(): void {
if (!this.btnClicked) return;

this.toggleIcons();
window.setTimeout(() => {
this.toggleIcons();
window.setTimeout(() => {
this.toggleIcons();
}, 1500);
}, Copy.FEEDBACK_DELAY);
}

private async copyToClipboard(codeBlock: HTMLElement): Promise<void> {
const sanitizedText = this.sanitizeContent(codeBlock);

if (!navigator.clipboard) {
console.error("Copy: Clipboard API is not supported in this browser.");
this.showFeedback();
return;
}

async copyToClipboard(codeBlock: HTMLElement) {
const sanitizedText = this.sanitizeContent(codeBlock);
try {
await navigator.clipboard.writeText(sanitizedText);
this.showFeedback();
} catch (err) {
console.error("Copy error: ", err);
this.showFeedback();
}
try {
await navigator.clipboard.writeText(sanitizedText);
console.info("Copy: Text copied successfully.");
this.showFeedback();
} catch (err) {
console.error("Copy: Error while copying text.", err);
this.showFeedback();
}
}
}

document.addEventListener("DOMContentLoaded", () => new Copy());
})();
export default () => new Copy();
42 changes: 42 additions & 0 deletions gno.land/pkg/gnoweb/frontend/js/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
(() => {
interface Module {
selector: string;
path: string;
}

const modules: Record<string, Module> = {
copy: {
selector: "[data-copy-btn]",
path: "/public/js/copy.js",
},
help: {
selector: "#data",
path: "/public/js/realmhelp.js",
},
searchBar: {
selector: "#header-searchbar",
path: "/public/js/searchbar.js",
},
};

const loadModuleIfExists = async ({ selector, path }: Module): Promise<void> => {
const element = document.querySelector(selector);
if (element) {
try {
const module = await import(path);
module.default();
} catch (err) {
console.error(`Error while loading script ${path}:`, err);
}
} else {
console.info(`Module not loaded: no element matches selector "${selector}"`);
}
};

const initModules = async (): Promise<void> => {
const promises = Object.values(modules).map((module) => loadModuleIfExists(module));
await Promise.all(promises);
};

document.addEventListener("DOMContentLoaded", initModules);
})();
Loading

0 comments on commit 58d9efc

Please sign in to comment.