@tixxin/nuxt-theme-engine 0.0.1 → 0.0.2
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/README.md +6 -2
- package/dist/default-contracts.d.mts +68 -0
- package/dist/default-contracts.mjs +11 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +14 -7
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -44,6 +44,8 @@
|
|
|
44
44
|
pnpm add @tixxin/nuxt-theme-engine
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
默认博客契约已经内置在 `@tixxin/nuxt-theme-engine` 发布包内,消费者**不需要额外安装** `@tixxin/theme-contracts`。
|
|
48
|
+
|
|
47
49
|
```ts
|
|
48
50
|
// nuxt.config.ts
|
|
49
51
|
export default defineNuxtConfig({
|
|
@@ -78,7 +80,9 @@ export default defineNuxtConfig({
|
|
|
78
80
|
|
|
79
81
|
引擎本身不强绑定某一套业务契约。
|
|
80
82
|
|
|
81
|
-
|
|
83
|
+
模块默认会使用内置的博客示例契约,等价导入路径为 `@tixxin/nuxt-theme-engine/default-contracts`。
|
|
84
|
+
|
|
85
|
+
仓库里的 `@tixxin/theme-contracts` 现在只是**开发期/示例来源**。如果你的项目是电商、文档站、社区或其他业务,可以直接换成自己的契约入口。
|
|
82
86
|
|
|
83
87
|
### 使用本地契约文件
|
|
84
88
|
|
|
@@ -145,7 +149,7 @@ pnpm dev
|
|
|
145
149
|
pnpm dev # 启动 playground
|
|
146
150
|
pnpm dev:prepare # 生成 .nuxt 类型声明
|
|
147
151
|
pnpm typecheck # 类型检查模块与 playground
|
|
148
|
-
pnpm build #
|
|
152
|
+
pnpm build # 构建主题引擎模块与内置默认契约
|
|
149
153
|
```
|
|
150
154
|
|
|
151
155
|
仓库结构:
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
interface ThemePostSummary {
|
|
2
|
+
id: string | number;
|
|
3
|
+
title: string;
|
|
4
|
+
excerpt?: string;
|
|
5
|
+
url?: string;
|
|
6
|
+
likesCount?: number;
|
|
7
|
+
commentsCount?: number;
|
|
8
|
+
readingTime?: string;
|
|
9
|
+
}
|
|
10
|
+
interface ThemePostDetail extends ThemePostSummary {
|
|
11
|
+
content: string;
|
|
12
|
+
}
|
|
13
|
+
interface HomeLayoutProps {
|
|
14
|
+
title?: string;
|
|
15
|
+
subtitle?: string;
|
|
16
|
+
}
|
|
17
|
+
interface PostListProps {
|
|
18
|
+
posts: ThemePostSummary[];
|
|
19
|
+
loading?: boolean;
|
|
20
|
+
}
|
|
21
|
+
interface PostDetailProps {
|
|
22
|
+
post: ThemePostDetail;
|
|
23
|
+
}
|
|
24
|
+
interface NavItem {
|
|
25
|
+
label: string;
|
|
26
|
+
icon?: string;
|
|
27
|
+
path: string;
|
|
28
|
+
}
|
|
29
|
+
interface SidebarNavProps {
|
|
30
|
+
items: NavItem[];
|
|
31
|
+
currentPath?: string;
|
|
32
|
+
}
|
|
33
|
+
interface SiteStatsData {
|
|
34
|
+
runningDays: number;
|
|
35
|
+
postCount: number;
|
|
36
|
+
viewCount: string;
|
|
37
|
+
commentCount: number;
|
|
38
|
+
tagCount: number;
|
|
39
|
+
}
|
|
40
|
+
interface SiteStatsProps {
|
|
41
|
+
stats: SiteStatsData;
|
|
42
|
+
}
|
|
43
|
+
interface SubscribeCardProps {
|
|
44
|
+
description?: string;
|
|
45
|
+
placeholder?: string;
|
|
46
|
+
}
|
|
47
|
+
interface BlogFooterProps {
|
|
48
|
+
copyright?: string;
|
|
49
|
+
poweredBy?: string;
|
|
50
|
+
links?: {
|
|
51
|
+
label: string;
|
|
52
|
+
url: string;
|
|
53
|
+
}[];
|
|
54
|
+
}
|
|
55
|
+
interface ThemeComponentContracts {
|
|
56
|
+
HomeLayout: HomeLayoutProps;
|
|
57
|
+
PostList: PostListProps;
|
|
58
|
+
PostDetail: PostDetailProps;
|
|
59
|
+
SidebarNav: SidebarNavProps;
|
|
60
|
+
SiteStats: SiteStatsProps;
|
|
61
|
+
SubscribeCard: SubscribeCardProps;
|
|
62
|
+
BlogFooter: BlogFooterProps;
|
|
63
|
+
}
|
|
64
|
+
declare const themeContractNames: readonly ["HomeLayout", "PostList", "PostDetail", "SidebarNav", "SiteStats", "SubscribeCard", "BlogFooter"];
|
|
65
|
+
type ThemeContractName = typeof themeContractNames[number];
|
|
66
|
+
|
|
67
|
+
export { themeContractNames };
|
|
68
|
+
export type { BlogFooterProps, HomeLayoutProps, NavItem, PostDetailProps, PostListProps, SidebarNavProps, SiteStatsData, SiteStatsProps, SubscribeCardProps, ThemeComponentContracts, ThemeContractName, ThemePostDetail, ThemePostSummary };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -470,6 +470,7 @@ async function checkCssVars(rootDir, themes, requiredCssVars) {
|
|
|
470
470
|
});
|
|
471
471
|
}
|
|
472
472
|
|
|
473
|
+
const DEFAULT_CONTRACTS_IMPORT_ID$1 = "@tixxin/nuxt-theme-engine/default-contracts";
|
|
473
474
|
function parseContractNames(source) {
|
|
474
475
|
const match = source.match(/themeContractNames\s*=\s*\[([\s\S]*?)\]\s*as const/);
|
|
475
476
|
if (!match) {
|
|
@@ -481,9 +482,10 @@ function parseContractNames(source) {
|
|
|
481
482
|
async function generateThemeComponentDts(contractsSourcePath, contractsImportId) {
|
|
482
483
|
const source = await promises.readFile(contractsSourcePath, "utf8");
|
|
483
484
|
const names = parseContractNames(source);
|
|
485
|
+
const importSource = contractsImportId || DEFAULT_CONTRACTS_IMPORT_ID$1;
|
|
484
486
|
const union = names.length > 0 ? names.map((name) => `'${name}'`).join(" | ") : "never";
|
|
485
487
|
return `import type { DefineComponent } from 'vue'
|
|
486
|
-
import type { ThemeComponentContracts } from ${JSON.stringify(
|
|
488
|
+
import type { ThemeComponentContracts } from ${JSON.stringify(importSource)}
|
|
487
489
|
|
|
488
490
|
declare module '#build/theme-engine.contracts.mjs' {
|
|
489
491
|
export const themeEngineContracts: {
|
|
@@ -691,14 +693,15 @@ async function loadThemeDefinitions(themesDir) {
|
|
|
691
693
|
return resolvedThemes.sort((left, right) => left.name.localeCompare(right.name));
|
|
692
694
|
}
|
|
693
695
|
|
|
696
|
+
const DEFAULT_CONTRACTS_IMPORT_ID = "@tixxin/nuxt-theme-engine/default-contracts";
|
|
694
697
|
const DEFAULTS = {
|
|
695
698
|
themesDir: "themes",
|
|
696
699
|
defaultTheme: "base",
|
|
697
700
|
cookieKey: "theme-pref",
|
|
698
701
|
lazyLoadThemes: false,
|
|
699
702
|
requiredCssVars: [],
|
|
700
|
-
contractsEntry:
|
|
701
|
-
contractsImportId:
|
|
703
|
+
contractsEntry: DEFAULT_CONTRACTS_IMPORT_ID,
|
|
704
|
+
contractsImportId: DEFAULT_CONTRACTS_IMPORT_ID
|
|
702
705
|
};
|
|
703
706
|
const require$1 = createRequire(import.meta.url);
|
|
704
707
|
async function pathExists(path) {
|
|
@@ -712,10 +715,12 @@ async function pathExists(path) {
|
|
|
712
715
|
function isLocalSpecifier(specifier) {
|
|
713
716
|
return specifier.startsWith(".") || specifier.startsWith("/") || specifier.startsWith("~") || /^[A-Za-z]:[\\/]/.test(specifier);
|
|
714
717
|
}
|
|
715
|
-
async function resolveContractsEntry(entry, importId, rootDir, moduleRoot, aliases) {
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
718
|
+
async function resolveContractsEntry(entry, importId, rootDir, moduleRoot, defaultContractsEntry, aliases) {
|
|
719
|
+
if (entry === DEFAULT_CONTRACTS_IMPORT_ID || importId === DEFAULT_CONTRACTS_IMPORT_ID) {
|
|
720
|
+
return defaultContractsEntry;
|
|
721
|
+
}
|
|
722
|
+
if (entry === "packages/theme-contracts/src/index.ts" && await pathExists(resolve(rootDir, entry))) {
|
|
723
|
+
return resolve(rootDir, entry);
|
|
719
724
|
}
|
|
720
725
|
const aliasTarget = aliases[entry] ?? aliases[importId];
|
|
721
726
|
if (typeof aliasTarget === "string") {
|
|
@@ -800,6 +805,7 @@ const module$1 = defineNuxtModule({
|
|
|
800
805
|
async setup(moduleOptions, nuxt) {
|
|
801
806
|
const resolver = createResolver(import.meta.url);
|
|
802
807
|
const moduleRoot = resolver.resolve("..");
|
|
808
|
+
const defaultContractsEntry = resolver.resolve("./default-contracts");
|
|
803
809
|
const options = {
|
|
804
810
|
...DEFAULTS,
|
|
805
811
|
...moduleOptions
|
|
@@ -811,6 +817,7 @@ const module$1 = defineNuxtModule({
|
|
|
811
817
|
contractsImportId,
|
|
812
818
|
nuxt.options.rootDir,
|
|
813
819
|
moduleRoot,
|
|
820
|
+
defaultContractsEntry,
|
|
814
821
|
nuxt.options.alias
|
|
815
822
|
);
|
|
816
823
|
const themes = await loadThemeDefinitions(themesDir);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tixxin/nuxt-theme-engine",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A Nuxt 4 theme engine with layered themes, typed contracts, and runtime theme switching.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
"types": "./dist/types.d.mts",
|
|
12
12
|
"import": "./dist/module.mjs"
|
|
13
13
|
},
|
|
14
|
+
"./default-contracts": {
|
|
15
|
+
"types": "./dist/default-contracts.d.mts",
|
|
16
|
+
"import": "./dist/default-contracts.mjs"
|
|
17
|
+
},
|
|
14
18
|
"./runtime/*": "./dist/runtime/*"
|
|
15
19
|
},
|
|
16
20
|
"files": [
|
|
@@ -19,7 +23,7 @@
|
|
|
19
23
|
"scripts": {
|
|
20
24
|
"dev": "nuxi dev playground",
|
|
21
25
|
"dev:prepare": "nuxi prepare playground",
|
|
22
|
-
"build": "
|
|
26
|
+
"build": "nuxt-module-build build",
|
|
23
27
|
"prepack": "pnpm build",
|
|
24
28
|
"lint": "eslint .",
|
|
25
29
|
"typecheck": "pnpm dev:prepare && tsc --noEmit -p tsconfig.json && vue-tsc --noEmit -p playground/.nuxt/tsconfig.json"
|
|
@@ -28,7 +32,6 @@
|
|
|
28
32
|
"nuxt": "^4.0.0"
|
|
29
33
|
},
|
|
30
34
|
"dependencies": {
|
|
31
|
-
"@tixxin/theme-contracts": "workspace:*",
|
|
32
35
|
"defu": "^6.1.6",
|
|
33
36
|
"fast-glob": "^3.3.3",
|
|
34
37
|
"pathe": "^2.0.3",
|