import { e as createAstro, f as createComponent, k as renderComponent, l as renderScript, r as renderTemplate, m as maybeRenderHead, h as addAttribute, u as unescapeHTML } from '../chunks/astro/server_CF97kUu8.mjs';
import 'piccolore';
import { _ as _export_sfc, $ as $$Base } from '../chunks/_plugin-vue_export-helper_CEgY73aA.mjs';
import { useSSRContext, defineComponent, ref, nextTick, mergeProps } from 'vue';
import { ssrRenderTeleport, ssrInterpolate, ssrRenderAttr, ssrIncludeBooleanAttr, ssrRenderAttrs } from 'vue/server-renderer';
import { g as getSkill, b as getForksOf } from '../chunks/skills_BacVQUiS.mjs';
import { h as hasToken } from '../chunks/tokens_CAzj9Aj8.mjs';
import { a as recordDownload, g as getStatsForSlug } from '../chunks/stats_CaDi9y9J.mjs';
import { marked } from 'marked';
/* empty css */
export { renderers } from '../renderers.mjs';
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
__name: "EditGate",
props: {
slug: {},
authorEmail: {},
authorName: {},
authorHasToken: { type: Boolean }
},
setup(__props, { expose: __expose }) {
__expose();
const props = __props;
const showModal = ref(false);
const token = ref("");
const error = ref("");
const verifying = ref(false);
const tokenInput = ref();
async function handleClick() {
if (!props.authorEmail || !props.authorHasToken) {
window.location.href = `/${props.slug}/edit`;
return;
}
const saved = localStorage.getItem("skillshere-token") || "";
if (saved) {
try {
const res = await fetch("/api/auth/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: props.authorEmail, token: saved })
});
if (res.ok) {
localStorage.setItem("skillshere-token", saved);
window.location.href = `/${props.slug}/edit`;
return;
}
} catch {
}
}
showModal.value = true;
error.value = "";
token.value = "";
nextTick(() => tokenInput.value?.focus());
}
async function verify() {
verifying.value = true;
error.value = "";
try {
const res = await fetch("/api/auth/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: props.authorEmail, token: token.value })
});
if (!res.ok) {
const data = await res.json();
error.value = data.error || "Invalid token";
return;
}
localStorage.setItem("skillshere-token", token.value);
window.location.href = `/${props.slug}/edit`;
} catch {
error.value = "Could not verify token";
} finally {
verifying.value = false;
}
}
function forkSkill() {
showModal.value = false;
window.location.href = `/new?from=${encodeURIComponent(props.slug)}`;
}
const __returned__ = { props, showModal, token, error, verifying, tokenInput, handleClick, verify, forkSkill };
Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
return __returned__;
}
});
function _sfc_ssrRender$1(_ctx, _push, _parent, _attrs, $props, $setup, $data, $options) {
_push(``);
ssrRenderTeleport(_push, (_push2) => {
if ($setup.showModal) {
_push2(`
Author Verification
This skill is owned by ${ssrInterpolate($props.authorName || $props.authorEmail)}. Enter your token to edit.
`);
} else {
_push2(``);
}
}, "body", false, _parent);
_push(``);
}
const _sfc_setup$1 = _sfc_main$1.setup;
_sfc_main$1.setup = (props, ctx) => {
const ssrContext = useSSRContext();
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("src/components/EditGate.vue");
return _sfc_setup$1 ? _sfc_setup$1(props, ctx) : void 0;
};
const EditGate = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["ssrRender", _sfc_ssrRender$1]]);
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "DeleteButton",
props: {
slug: {},
authorEmail: {},
authorName: {},
authorHasToken: { type: Boolean }
},
setup(__props, { expose: __expose }) {
__expose();
const props = __props;
const deleting = ref(false);
const showModal = ref(false);
const token = ref("");
const error = ref("");
const tokenInput = ref();
async function handleClick() {
if (props.authorEmail && props.authorHasToken) {
const saved = localStorage.getItem("skillshere-token") || "";
if (saved) {
try {
const res = await fetch("/api/auth/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: props.authorEmail, token: saved })
});
if (res.ok) {
doDelete(saved);
return;
}
} catch {
}
}
showModal.value = true;
error.value = "";
token.value = "";
nextTick(() => tokenInput.value?.focus());
} else {
doDelete("");
}
}
async function verifyAndDelete() {
error.value = "";
deleting.value = true;
try {
const verifyRes = await fetch("/api/auth/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: props.authorEmail, token: token.value })
});
if (!verifyRes.ok) {
const data = await verifyRes.json();
error.value = data.error || "Invalid token";
deleting.value = false;
return;
}
} catch {
error.value = "Could not verify token";
deleting.value = false;
return;
}
localStorage.setItem("skillshere-token", token.value);
doDelete(token.value);
}
async function doDelete(authToken) {
if (!confirm(`Delete "${props.slug}"? This cannot be undone.`)) {
deleting.value = false;
return;
}
deleting.value = true;
error.value = "";
try {
const headers = {};
if (authToken) {
headers["Authorization"] = `Bearer ${authToken}`;
}
const res = await fetch(`/api/skills/${props.slug}`, { method: "DELETE", headers });
if (res.status === 403) {
const data = await res.json();
error.value = data.error || "Permission denied";
showModal.value = true;
deleting.value = false;
return;
}
if (!res.ok && res.status !== 204) {
const data = await res.json().catch(() => ({ error: "Failed to delete" }));
throw new Error(data.error || "Failed to delete");
}
window.location.href = "/";
} catch (err) {
error.value = err instanceof Error ? err.message : "Failed to delete skill.";
deleting.value = false;
}
}
const __returned__ = { props, deleting, showModal, token, error, tokenInput, handleClick, verifyAndDelete, doDelete };
Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
return __returned__;
}
});
function _sfc_ssrRender(_ctx, _push, _parent, _attrs, $props, $setup, $data, $options) {
_push(``);
ssrRenderTeleport(_push, (_push2) => {
if ($setup.showModal) {
_push2(`
Delete Skill
This skill is owned by ${ssrInterpolate($props.authorName || $props.authorEmail)}. Enter your token to delete it.
`);
} else {
_push2(``);
}
}, "body", false, _parent);
_push(`
`);
}
const _sfc_setup = _sfc_main.setup;
_sfc_main.setup = (props, ctx) => {
const ssrContext = useSSRContext();
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("src/components/DeleteButton.vue");
return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
};
const DeleteButton = /* @__PURE__ */ _export_sfc(_sfc_main, [["ssrRender", _sfc_ssrRender]]);
const $$Astro = createAstro("https://skills.here.run.place");
const $$slug = createComponent(async ($$result, $$props, $$slots) => {
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
Astro2.self = $$slug;
const { slug } = Astro2.params;
const skill = await getSkill(slug);
if (!skill) {
return Astro2.redirect("/");
}
const accept = Astro2.request.headers.get("accept") || "";
if (!accept.includes("text/html")) {
recordDownload(slug);
return new Response(skill.raw, {
headers: { "Content-Type": "text/markdown; charset=utf-8" }
});
}
const authorHasToken = skill["author-email"] ? await hasToken(skill["author-email"]) : false;
const forks = await getForksOf(slug);
const stats = await getStatsForSlug(slug);
const html = await marked(skill.content);
const origin = Astro2.url.origin;
const cmds = {
unix: `curl -fsSL ${origin}/${slug}/i | bash`,
unixGlobal: `curl -fsSL ${origin}/${slug}/gi | bash`,
win: `irm ${origin}/${slug}/i | iex`,
winGlobal: `irm ${origin}/${slug}/gi | iex`
};
return renderTemplate`${renderComponent($$result, "Base", $$Base, { "title": `${skill.name} \u2014 Skills Here`, "data-astro-cid-yvbahnfj": true }, { "default": async ($$result2) => renderTemplate` ${maybeRenderHead()}
Back
${skill.name}
${skill.description && renderTemplate`
${skill.description}
`} ${skill["allowed-tools"].length > 0 && renderTemplate`
${skill["allowed-tools"].map((tool) => renderTemplate` ${tool} `)}
`} ${skill.tags.length > 0 && renderTemplate`
${skill.tags.map((tag) => renderTemplate` ${tag} `)}
`} ${skill.author && renderTemplate`
by ${skill.author}
`} ${skill["fork-of"] && renderTemplate`
forked from ${skill["fork-of"]}
`} ${forks.length > 0 && renderTemplate`
${forks.length} fork${forks.length !== 1 ? "s" : ""}
`}
${stats.downloads} download${stats.downloads !== 1 ? "s" : ""} ${stats.pushes} push${stats.pushes !== 1 ? "es" : ""} ${stats.lastPushedAt && renderTemplate`
Last updated ${new Date(stats.lastPushedAt).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })} `}
Install this skill
Run in your project root to add this skill.
${cmds.unix} ${cmds.win}
More options
Install globally (available in all projects):
${cmds.unixGlobal} ${cmds.winGlobal}
${renderComponent($$result2, "EditGate", EditGate, { "slug": slug, "authorEmail": skill["author-email"], "authorName": skill.author, "authorHasToken": authorHasToken, "client:load": true, "client:component-hydration": "load", "client:component-path": "/Users/alex/projects/skillit/src/components/EditGate.vue", "client:component-export": "default", "data-astro-cid-yvbahnfj": true })} ${renderComponent($$result2, "DeleteButton", DeleteButton, { "slug": slug, "authorEmail": skill["author-email"], "authorName": skill.author, "authorHasToken": authorHasToken, "client:load": true, "client:component-hydration": "load", "client:component-path": "/Users/alex/projects/skillit/src/components/DeleteButton.vue", "client:component-export": "default", "data-astro-cid-yvbahnfj": true })}
${unescapeHTML(html)} ` })} ${renderScript($$result, "/Users/alex/projects/skillit/src/pages/[slug].astro?astro&type=script&index=0&lang.ts")}`;
}, "/Users/alex/projects/skillit/src/pages/[slug].astro", void 0);
const $$file = "/Users/alex/projects/skillit/src/pages/[slug].astro";
const $$url = "/[slug]";
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
__proto__: null,
default: $$slug,
file: $$file,
url: $$url
}, Symbol.toStringTag, { value: 'Module' }));
const page = () => _page;
export { page };