update
This commit is contained in:
1 parent
c7f4bad142
commit
9fd12d3e74
9 files changed
+787
-9
No files matched your search
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<form @submit="onSubmit">
|
||||
<input type="text" v-model="q">
|
||||
<button type="submit">Submit</button>
|
||||
|
||||
<video controls ref="video" :src="videoSrc" @loadeddata="onVideoLoad" @seeked="onSeeked"></video>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, useTemplateRef, VNodeRef } from 'vue'
|
||||
|
||||
const q = ref('')
|
||||
const videoSrc = ref('')
|
||||
const videoEl = useTemplateRef('video')
|
||||
|
||||
function onSubmit(ev: SubmitEvent) {
|
||||
ev.preventDefault()
|
||||
|
||||
if (!q.value) return
|
||||
|
||||
videoSrc.value = '/public/' + q.value
|
||||
}
|
||||
|
||||
function onVideoLoad() {
|
||||
const { hot } = import.meta as any
|
||||
hot.send('download-q', { q: q.value.replace(/\.[a-z0-9]+$/, '') })
|
||||
|
||||
hot.on('seek-q', ({ t }: { t: number }) => {
|
||||
videoEl.value!.currentTime = t;
|
||||
})
|
||||
}
|
||||
|
||||
function onSeeked() {
|
||||
const v = videoEl.value!
|
||||
let c = document.createElement('canvas');
|
||||
c.height = v.videoHeight || parseInt(v.style.height);
|
||||
c.width = v.videoWidth || parseInt(v.style.width);
|
||||
const ctx = c.getContext('2d')!;
|
||||
ctx.drawImage(v, 0, 0);
|
||||
|
||||
const { hot } = import.meta as any
|
||||
hot.send('timed-q', { q: q.value.replace(/\.[a-z0-9]+$/, ''), t: videoEl.value!.currentTime, data: c.toDataURL('image/png') })
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
form {
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
form * {
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-left: 0.5em;
|
||||
cursor: pointer;
|
||||
padding: 0 0.5em;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { Theme } from "vitepress";
|
||||
import DefaultTheme from "vitepress/theme";
|
||||
import Downloader from "./components/Downloader.vue";
|
||||
import ytParsePlugin from "./plugins/yt-parse";
|
||||
|
||||
export default {
|
||||
extends: DefaultTheme,
|
||||
enhanceApp({ app }) {
|
||||
// register your custom global components
|
||||
app.component("Downloader", Downloader);
|
||||
app.use(ytParsePlugin);
|
||||
},
|
||||
} satisfies Theme;
|
||||
@@ -0,0 +1,41 @@
|
||||
import { type Plugin, type ViteDevServer } from "vite";
|
||||
import { readFileSync, mkdirSync, writeFileSync } from "fs";
|
||||
|
||||
export default function ytParsePlugin(): Plugin {
|
||||
return {
|
||||
name: "clipboard-server-spawn",
|
||||
configureServer(server: ViteDevServer) {
|
||||
server.ws.on("download-q", ({ q }) => {
|
||||
try {
|
||||
mkdirSync(`docs/${q}`);
|
||||
} catch (e) {}
|
||||
|
||||
let outMd = "";
|
||||
|
||||
const re = /^(?<min>\d{1,2}):(?<sec>\d{2})\s*$/;
|
||||
|
||||
for (const line of readFileSync(`docs/${q}.md`, "utf-8").trimEnd().split("\n")) {
|
||||
const m = re.exec(line);
|
||||
if (m) {
|
||||
const { min, sec } = m.groups!;
|
||||
const t = parseInt(min) * 60 + parseInt(sec);
|
||||
server.ws.send("seek-q", { t });
|
||||
outMd += `[${line}](./${q}/${t}.png)`;
|
||||
} else {
|
||||
outMd += line + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
writeFileSync(`docs/${q}.md`, outMd);
|
||||
});
|
||||
|
||||
server.ws.on("timed-q", ({ q, t, data }) => {
|
||||
writeFileSync(
|
||||
`docs/${q}/${t}.png`,
|
||||
data.replace(/^data:image\/png;base64,/, ""),
|
||||
"base64",
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user