create-valaxy 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import x from"node:process";import r from"node:fs";import l from"node:path";import{fileURLToPath as U}from"node:url";import{colors as t}from"consola/utils";import{execa as E}from"execa";import J from"minimist";import v from"prompts";const Y="1.0
|
|
1
|
+
import x from"node:process";import r from"node:fs";import l from"node:path";import{fileURLToPath as U}from"node:url";import{colors as t}from"consola/utils";import{execa as E}from"execa";import J from"minimist";import v from"prompts";const Y="1.1.0",N={name:"starter",repo:"https://github.com/valaxyjs/valaxy-theme-starter"};async function G(e){const n=N.name;let o=e.themeName||n;const d=`valaxy-theme-${o.trim()}`;return console.log(` ${t.dim("npx")} ${t.gray("degit")} ${t.blue(N.repo)} ${t.yellow(d)}`),await E("npx",["degit",N.repo,d],{stdio:"inherit"}),console.log(),console.log(` ${t.bold("Check it")}:`),console.log(),console.log(`- Change ${t.bold("author")} name in ${t.yellow("LICENSE")} & ${t.green("package.json")} & ${t.blue(".github")}`),console.log(`- Change ${t.blue("valaxy.config.ts")} theme: ${t.yellow("starter")} to ${t.cyan(`${o}`)}`),console.log(`- Rename ${t.yellow(`valaxy-theme-${o}`)} to ${t.cyan(`valaxy-theme-${o}`)}`),console.log(),console.log(` ${t.cyan("\u2728")}`),console.log(),`valaxy-theme-${o}`}const W={_gitignore:".gitignore",_npmrc:".npmrc"},Z=[{name:"yun",display:"Yun",desc:"A light & clean theme (default)",color:t.cyan},{name:"press",display:"Press",desc:"A document-oriented theme",color:t.green},{name:"custom",display:"Custom",desc:"Enter a custom theme name",color:t.yellow}],w=[{name:"blog",display:"Blog",desc:"For Most Users",message:"Project name:",initial:"valaxy-blog",color:t.cyan},{name:"theme",display:"Theme",desc:"For Theme Developers",message:"Theme name: valaxy-theme-",initial:"starter",prefix:"valaxy-theme-",color:t.green,customInit:async e=>G(e).catch(n=>{console.error(n)})},{name:"addon",display:"Addon",desc:"For Addon Developers",message:"Addon name: valaxy-addon-",initial:"template",prefix:"valaxy-addon-",color:t.yellow}],_=w.map(e=>e.name),z="valaxy-theme-",q=/^[a-z\d\-_]+$/,K=U(import.meta.url);function L(e){if(!q.test(e))throw new Error(`Invalid theme name: "${e}"`);return l.resolve(K,"../..",`template-blog-${e}`)}function Q(e){try{return r.existsSync(L(e))}catch{return!1}}function X(e){const n=e.trim();return n.startsWith(z)?n.slice(z.length):n}function ee(e,n){const o={...e,dependencies:{...e.dependencies}};return n==="yun"||(o.dependencies?.["valaxy-theme-yun"]&&delete o.dependencies["valaxy-theme-yun"],o.dependencies[`valaxy-theme-${n}`]=n==="press"&&o.dependencies.valaxy||"latest"),o}function te(e,n){if(n==="yun")return e;let o=e;return o=o.replace("import type { UserThemeConfig } from 'valaxy-theme-yun'",`// import type { UserThemeConfig } from 'valaxy-theme-${n}'`),o=o.replace("theme: 'yun'",`theme: '${n}'`),o=o.replace("defineValaxyConfig<UserThemeConfig>","defineValaxyConfig"),o=o.replace(/themeConfig: \{[\s\S]*?\n {2}\},/,"themeConfig: {},"),o}function O(e){return e?.trim().replace(/\/+$/g,"")}function M(e){const n=r.readdirSync(e);return n.length===0||n.length===1&&n[0]===".git"}function F(e,n){r.statSync(e).isDirectory()?ne(e,n):r.copyFileSync(e,n)}function ne(e,n){r.mkdirSync(n,{recursive:!0});for(const o of r.readdirSync(e)){const d=l.resolve(e,o),g=l.resolve(n,o);F(d,g)}}function oe(e){if(console.log(`
|
|
2
2
|
${t.red("Removing")} ${t.dim(e)}`),!!r.existsSync(e))for(const n of r.readdirSync(e))n!==".git"&&r.rmSync(l.resolve(e,n),{recursive:!0,force:!0})}function R(e){return/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(e)}function P(e){return e.trim().toLowerCase().replace(/\s+/g,"-").replace(/^[._]/,"").replace(/[^a-z\d\-~]+/g,"-")}function ae(e){if(!e)return;const n=e.split(" ")[0].split("/");return{name:n[0],version:n[1]}}const u=J(x.argv.slice(2)),D=x.cwd(),re="valaxy-blog",ie=U(import.meta.url);async function le(){console.log(),console.log(` ${t.bold("\u{1F30C} Valaxy")} ${t.blue(`v${Y}`)}`),console.log();const e=O(u._[0]),n=u.template||u.t,o=u.y||u.yes,d=u.port||u.p;let g=e||re;const S=()=>g==="."?l.basename(l.resolve()):g;let b;const C=w.find(c=>c.name===n);if(o&&n&&!C)throw new Error(`Unknown template: ${n}. Choose ${_.join(", ")}.`);let i=C||w[0],f="yun";if(o)b={projectName:g,overwrite:!1,packageName:P(S())};else{const c=await v({type:n&&_.includes(n)?null:"select",name:"template",message:typeof n=="string"&&!_.includes(n)?t.reset(`"${n}" isn't a valid template. Please choose from below: `):t.reset("Select a type:"),initial:0,choices:w.map(a=>{const p=a.color;return{title:p(a.display||a.name)+t.dim(` - ${a.desc}`),value:a}})});if(!C&&!c.template)return;if(i=c.template||i,i.name==="blog"){const a=await v({type:"select",name:"theme",message:t.reset("Select a theme:"),initial:0,choices:Z.map(p=>{const h=p.color;return{title:h(p.display)+t.dim(` - ${p.desc}`),value:p.name}})});if(a.theme==="custom"){const p=await v({type:"text",name:"themeName",message:t.reset('Theme name (e.g. "starter" or "valaxy-theme-starter"):'),initial:"yun"});f=X(p.themeName||"yun")}else f=a.theme||"yun"}try{b=await v([{type:e?null:"text",name:"projectName",message:t.reset(i.message),initial:i.initial,onState:a=>{g=O(i.prefix?i.prefix+a.value:a.value)||i.initial}},{type:()=>!r.existsSync(g)||M(g)?null:"confirm",name:"overwrite",message:()=>`${g==="."?"Current directory":`Target directory "${g}"`} is not empty. Remove existing files and continue?`},{type:(a,{overwrite:p})=>{if(p===!1)throw new Error(`${t.red("\u2716")} Operation cancelled`);return null},name:"overwriteChecker"},{type:()=>R(S())?null:"text",name:"packageName",message:t.reset("Package name:"),initial:()=>P(S()),validate:a=>R(a)||"Invalid package.json name"}],{onCancel:()=>{throw new Error(`${t.red("\u2716")} Operation cancelled`)}})}catch(a){console.log(a.message);return}}const{projectName:T=g,overwrite:V,packageName:H}=b,I=e||(i.prefix?i.prefix+T:T),s=l.resolve(D,I);if(o&&r.existsSync(s)&&!M(s))throw new Error(`Target directory "${I}" is not empty. Run without --yes to confirm overwriting.`);if(V?oe(s):r.existsSync(s)||r.mkdirSync(s,{recursive:!0}),i.customInit)await i.customInit({themeName:T});else{const c=l.resolve(ie,"../..",`template-${i.name}`),a=(m,y)=>{const $=l.join(s,W[m]??m);y?r.writeFileSync($,y):F(l.join(c,m),$)},p=r.readdirSync(c);for(const m of p.filter(y=>y!=="package.json"))a(m);const h=JSON.parse(r.readFileSync(l.join(c,"package.json"),"utf-8"));if(h.name=H||P(l.basename(s)),i.name==="blog"){const m=ee(h,f);Object.assign(h,m)}if(a("package.json",`${JSON.stringify(h,null,2)}
|
|
3
3
|
`),i.name==="blog")if(Q(f)){const m=L(f),y=r.readdirSync(m);for(const $ of y)F(l.join(m,$),l.join(s,$))}else{const m=l.join(s,"valaxy.config.ts");if(r.existsSync(m)){const y=r.readFileSync(m,"utf-8");r.writeFileSync(m,te(y,f))}}}console.log(` ${t.dim("\u{1F4C1}")} ${t.dim(s)}`),console.log(),console.log(t.dim(" Scaffolding project in ")+g+t.dim(" ..."));const A=ae(x.env.npm_config_user_agent),j=A?A.name:"npm",B=l.relative(D,s);if(console.log(t.green(` Done.
|
|
4
4
|
`)),i.name==="addon")return;let k;if(o?k=!1:{yes:k}=await v({type:"confirm",name:"yes",initial:"Y",message:"Install and start it now?"}),k){let c;if(o?c="pnpm":{agent:c}=await v({name:"agent",type:"select",message:"Choose the agent",choices:["npm","yarn","pnpm","bun"].map(a=>({value:a,title:a})),initial:2}),!c)return;await E(c,["install"],{stdio:"inherit",cwd:s}),await E(c,d?["run","dev","--port",d]:["run","dev"],{stdio:"inherit",cwd:s})}else{switch(console.log(t.dim(`
|
package/package.json
CHANGED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { onMounted, onUnmounted, shallowRef, useId, useTemplateRef } from 'vue'
|
|
3
|
+
|
|
4
|
+
withDefaults(defineProps<{
|
|
5
|
+
context?: 'card' | 'page' | 'body'
|
|
6
|
+
subtitle?: string
|
|
7
|
+
}>(), {
|
|
8
|
+
context: 'body',
|
|
9
|
+
subtitle: 'Your words, a new constellation.',
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const id = useId()
|
|
13
|
+
const root = shallowRef<HTMLElement>()
|
|
14
|
+
const svg = useTemplateRef<SVGSVGElement>('svg')
|
|
15
|
+
defineExpose({ svg })
|
|
16
|
+
const illuminated = shallowRef(false)
|
|
17
|
+
const inView = shallowRef(false)
|
|
18
|
+
const pageVisible = shallowRef(true)
|
|
19
|
+
// Fixed coordinates keep the server render and the first client render identical.
|
|
20
|
+
const stars = Array.from({ length: 36 }, (_, i) => ({
|
|
21
|
+
x: (i * 137 + 41) % 960,
|
|
22
|
+
y: (i * 73 + 29) % 410,
|
|
23
|
+
r: i % 4 === 0 ? 2 : 1,
|
|
24
|
+
}))
|
|
25
|
+
const constellation = [[530, 110], [570, 165], [615, 228], [660, 290], [707, 215], [754, 150], [794, 88]]
|
|
26
|
+
let observer: IntersectionObserver | undefined
|
|
27
|
+
function updateVisibility() {
|
|
28
|
+
pageVisible.value = document.visibilityState !== 'hidden'
|
|
29
|
+
}
|
|
30
|
+
onMounted(() => {
|
|
31
|
+
updateVisibility()
|
|
32
|
+
document.addEventListener('visibilitychange', updateVisibility)
|
|
33
|
+
if (typeof IntersectionObserver !== 'undefined') {
|
|
34
|
+
observer = new IntersectionObserver(([entry]) => {
|
|
35
|
+
inView.value = entry.isIntersecting
|
|
36
|
+
})
|
|
37
|
+
if (root.value)
|
|
38
|
+
observer.observe(root.value)
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
inView.value = true
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
onUnmounted(() => {
|
|
45
|
+
observer?.disconnect()
|
|
46
|
+
document.removeEventListener('visibilitychange', updateVisibility)
|
|
47
|
+
})
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<template>
|
|
51
|
+
<div
|
|
52
|
+
ref="root" class="hello-valaxy-cover" :data-context="context"
|
|
53
|
+
:class="{ illuminated, playing: illuminated && inView && pageVisible, compact: context === 'card' }"
|
|
54
|
+
>
|
|
55
|
+
<svg ref="svg" class="hello-valaxy-sky" viewBox="0 0 960 540" preserveAspectRatio="xMinYMid slice" aria-hidden="true" focusable="false">
|
|
56
|
+
<defs>
|
|
57
|
+
<linearGradient :id="`${id}-sky`" x2="0.8" y2="1">
|
|
58
|
+
<stop stop-color="#102751" />
|
|
59
|
+
<stop offset="0.65" stop-color="#225d93" />
|
|
60
|
+
<stop offset="1" stop-color="#7cc9da" />
|
|
61
|
+
</linearGradient>
|
|
62
|
+
<radialGradient :id="`${id}-halo`">
|
|
63
|
+
<stop stop-color="#95e5ed" stop-opacity="0.3" />
|
|
64
|
+
<stop offset="1" stop-color="#95e5ed" stop-opacity="0" />
|
|
65
|
+
</radialGradient>
|
|
66
|
+
<linearGradient :id="`${id}-caption`">
|
|
67
|
+
<stop stop-color="#091b3b" stop-opacity="0.65" />
|
|
68
|
+
<stop offset="0.8" stop-color="#091b3b" stop-opacity="0" />
|
|
69
|
+
</linearGradient>
|
|
70
|
+
</defs>
|
|
71
|
+
<path d="M0 0H960V540H0Z" :fill="`url(#${id}-sky)`" />
|
|
72
|
+
<circle cx="670" cy="210" r="250" :fill="`url(#${id}-halo)`" />
|
|
73
|
+
<g fill="#daefff" opacity="0.6">
|
|
74
|
+
<circle v-for="(star, i) in stars" :key="i" :cx="star.x" :cy="star.y" :r="star.r" />
|
|
75
|
+
</g>
|
|
76
|
+
<g class="hello-valaxy-orbits" fill="none" stroke="#b8e5f3">
|
|
77
|
+
<circle cx="660" cy="208" r="158" opacity="0.2" />
|
|
78
|
+
<ellipse cx="660" cy="208" rx="212" ry="66" transform="rotate(-28 660 208)" opacity="0.25" />
|
|
79
|
+
<g class="hello-valaxy-orbit hello-valaxy-motion">
|
|
80
|
+
<circle cx="818" cy="208" r="5" fill="#b5f1ee" stroke="none" />
|
|
81
|
+
<circle cx="818" cy="208" r="11" opacity="0.3" />
|
|
82
|
+
</g>
|
|
83
|
+
</g>
|
|
84
|
+
<g fill="none" stroke="#c4f6ff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
85
|
+
<path d="M530 110 570 165 615 228 660 290 707 215 754 150 794 88" opacity="0.18" />
|
|
86
|
+
<path class="hello-valaxy-constellation" d="M530 110 570 165 615 228 660 290 707 215 754 150 794 88" pathLength="1" />
|
|
87
|
+
</g>
|
|
88
|
+
<g class="hello-valaxy-stars" fill="#e0fcff">
|
|
89
|
+
<g v-for="([x, y], i) in constellation" :key="i">
|
|
90
|
+
<circle class="hello-valaxy-glow" :cx="x" :cy="y" r="12" />
|
|
91
|
+
<path :d="`M${x - 6} ${y}h12M${x} ${y - 6}v12`" stroke="currentColor" />
|
|
92
|
+
<circle :cx="x" :cy="y" r="3" />
|
|
93
|
+
</g>
|
|
94
|
+
</g>
|
|
95
|
+
<g class="hello-valaxy-clouds hello-valaxy-motion">
|
|
96
|
+
<path d="M-40 460Q30 366 110 420Q148 340 242 408Q304 369 374 433Q440 347 528 408Q605 350 690 425Q790 335 886 410Q954 385 1000 443V570H-40Z" fill="#6faecb" opacity="0.35" />
|
|
97
|
+
<path d="M-40 494Q60 416 148 474Q223 403 326 473Q405 428 473 487Q565 391 660 466Q748 412 835 474Q920 404 1000 478V570H-40Z" fill="#b4e4e9" opacity="0.4" />
|
|
98
|
+
</g>
|
|
99
|
+
<path d="M0 0H960V540H0Z" :fill="`url(#${id}-caption)`" />
|
|
100
|
+
<g fill="#f4fbff">
|
|
101
|
+
<text x="60" y="342" :style="{ fontFamily: 'Georgia, serif', fontSize: context === 'card' ? '74px' : '64px', fontWeight: 800 }">Hello, Valaxy!</text>
|
|
102
|
+
<text x="60" y="388" :style="{ fontFamily: 'sans-serif', fontSize: context === 'card' ? '28px' : '22px' }">{{ subtitle }}</text>
|
|
103
|
+
</g>
|
|
104
|
+
</svg>
|
|
105
|
+
<div class="hello-valaxy-caption">
|
|
106
|
+
<span class="hello-valaxy-description">Hello, Valaxy! {{ subtitle }}</span>
|
|
107
|
+
<button type="button" :aria-pressed="illuminated" @click="illuminated = !illuminated">
|
|
108
|
+
{{ illuminated ? 'Stars are shining' : 'Light up the stars' }}
|
|
109
|
+
</button>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
</template>
|
|
113
|
+
|
|
114
|
+
<style scoped>
|
|
115
|
+
.hello-valaxy-cover {
|
|
116
|
+
position: relative;
|
|
117
|
+
isolation: isolate;
|
|
118
|
+
width: 100%;
|
|
119
|
+
height: auto;
|
|
120
|
+
min-height: 12rem;
|
|
121
|
+
aspect-ratio: 16 / 9;
|
|
122
|
+
overflow: hidden;
|
|
123
|
+
color: #f4fbff;
|
|
124
|
+
background: #102751;
|
|
125
|
+
border-radius: inherit;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.hello-valaxy-cover[data-context="card"],
|
|
129
|
+
.hello-valaxy-cover[data-context="page"] {
|
|
130
|
+
height: 100%;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.hello-valaxy-sky {
|
|
134
|
+
position: absolute;
|
|
135
|
+
inset: 0;
|
|
136
|
+
width: 100%;
|
|
137
|
+
height: 100%;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.hello-valaxy-caption {
|
|
141
|
+
position: absolute;
|
|
142
|
+
inset: 0;
|
|
143
|
+
display: flex;
|
|
144
|
+
flex-direction: column;
|
|
145
|
+
align-items: flex-start;
|
|
146
|
+
justify-content: flex-end;
|
|
147
|
+
padding: clamp(1rem, 4vw, 2.5rem);
|
|
148
|
+
pointer-events: none;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.hello-valaxy-description {
|
|
152
|
+
position: absolute;
|
|
153
|
+
width: 1px;
|
|
154
|
+
height: 1px;
|
|
155
|
+
overflow: hidden;
|
|
156
|
+
clip-path: inset(50%);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.hello-valaxy-caption button {
|
|
160
|
+
padding: 0.4rem 0.8rem;
|
|
161
|
+
border: 1px solid rgb(220 245 255 / 0.65);
|
|
162
|
+
border-radius: 2rem;
|
|
163
|
+
color: inherit;
|
|
164
|
+
background: #153c64;
|
|
165
|
+
font: inherit;
|
|
166
|
+
font-size: 0.8rem;
|
|
167
|
+
cursor: pointer;
|
|
168
|
+
pointer-events: auto;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.hello-valaxy-caption button:focus-visible {
|
|
172
|
+
outline: 2px solid #c4f6ff;
|
|
173
|
+
outline-offset: 4px;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.hello-valaxy-constellation {
|
|
177
|
+
stroke-dasharray: 1;
|
|
178
|
+
stroke-dashoffset: 1;
|
|
179
|
+
transition: stroke-dashoffset 900ms ease;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.illuminated .hello-valaxy-constellation {
|
|
183
|
+
stroke-dashoffset: 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.hello-valaxy-glow {
|
|
187
|
+
opacity: 0;
|
|
188
|
+
transition: opacity 600ms ease;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.illuminated .hello-valaxy-glow {
|
|
192
|
+
opacity: 0.2;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.hello-valaxy-orbit {
|
|
196
|
+
transform-origin: 660px 208px;
|
|
197
|
+
animation: hello-valaxy-orbit 24s linear infinite;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.hello-valaxy-clouds {
|
|
201
|
+
animation: hello-valaxy-drift 12s ease-in-out infinite alternate;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.hello-valaxy-motion {
|
|
205
|
+
animation-play-state: paused;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.playing .hello-valaxy-motion {
|
|
209
|
+
animation-play-state: running;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.compact .hello-valaxy-caption {
|
|
213
|
+
padding: 1rem;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
@keyframes hello-valaxy-orbit {
|
|
217
|
+
to { transform: rotate(360deg); }
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
@keyframes hello-valaxy-drift {
|
|
221
|
+
to { transform: translate(18px, -8px); }
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
@media (prefers-reduced-motion: reduce) {
|
|
225
|
+
.hello-valaxy-motion {
|
|
226
|
+
animation: none;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.hello-valaxy-constellation,
|
|
230
|
+
.hello-valaxy-glow {
|
|
231
|
+
transition: none;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
</style>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Hello, Valaxy!
|
|
3
|
+
coverComponent: HelloValaxyCover
|
|
3
4
|
date: 2022-04-01
|
|
4
5
|
updated: 2022-04-01
|
|
5
6
|
categories: Valaxy 笔记
|
|
@@ -15,6 +16,12 @@ Next Generation Static Blog Framework.
|
|
|
15
16
|
|
|
16
17
|
Write your first post!
|
|
17
18
|
|
|
19
|
+
## Vue in Markdown
|
|
20
|
+
|
|
21
|
+
Components in `components/` can be used directly in Markdown. This cover uses Vue and inline SVG without image assets. Click to light up the constellation; click again to pause:
|
|
22
|
+
|
|
23
|
+
<HelloValaxyCover subtitle="The same component, inside your story." />
|
|
24
|
+
|
|
18
25
|
## Usage
|
|
19
26
|
|
|
20
27
|
Modify `valaxy.config.ts` to custom your blog.
|