@open-dy/vibecoding-sdk-taro 0.0.1-beta.1

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.
Files changed (239) hide show
  1. package/dist/adapters/interest-card/eslint/eslint-plugin-custom-navigation.mjs +290 -0
  2. package/dist/adapters/interest-card/eslint/taro.mjs +55 -0
  3. package/dist/adapters/interest-card/runtime/microapp.d.ts +7 -0
  4. package/dist/adapters/interest-card/runtime/microapp.js +8 -0
  5. package/dist/adapters/interest-card/runtime/microapp.js.map +1 -0
  6. package/dist/adapters/interest-card/types/taro.d.ts +28 -0
  7. package/dist/build/config-overrides.d.ts +19 -0
  8. package/dist/build/config-overrides.js +35 -0
  9. package/dist/build/config-overrides.js.map +1 -0
  10. package/dist/build/index.d.ts +1 -0
  11. package/dist/build/index.js +2 -0
  12. package/dist/build/index.js.map +1 -0
  13. package/dist/build/plugins/app-config.cjs +43 -0
  14. package/dist/build/plugins/vite-depend-card.d.ts +29 -0
  15. package/dist/build/plugins/vite-depend-card.js +250 -0
  16. package/dist/build/plugins/vite-depend-card.js.map +1 -0
  17. package/dist/build/plugins/vite-image-asset-import.d.ts +10 -0
  18. package/dist/build/plugins/vite-image-asset-import.js +150 -0
  19. package/dist/build/plugins/vite-image-asset-import.js.map +1 -0
  20. package/dist/build/plugins/vite-inline-json.d.ts +4 -0
  21. package/dist/build/plugins/vite-inline-json.js +129 -0
  22. package/dist/build/plugins/vite-inline-json.js.map +1 -0
  23. package/dist/build/plugins/vite-taro-source-location.d.ts +13 -0
  24. package/dist/build/plugins/vite-taro-source-location.js +159 -0
  25. package/dist/build/plugins/vite-taro-source-location.js.map +1 -0
  26. package/dist/build/taro.d.ts +53 -0
  27. package/dist/build/taro.js +729 -0
  28. package/dist/build/taro.js.map +1 -0
  29. package/dist/components/miniapp-open-card.d.ts +19 -0
  30. package/dist/components/miniapp-open-card.js +3 -0
  31. package/dist/components/miniapp-open-card.js.map +1 -0
  32. package/dist/eslint/eslint-plugin-microapp-pages.mjs +659 -0
  33. package/dist/eslint/server.mjs +69 -0
  34. package/dist/eslint/taro.mjs +553 -0
  35. package/dist/index.d.ts +2 -0
  36. package/dist/index.js +3 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/internal/runtime/douyin-open-button.d.ts +29 -0
  39. package/dist/internal/runtime/iframe-auth/identity.d.ts +20 -0
  40. package/dist/internal/runtime/iframe-auth/identity.js +156 -0
  41. package/dist/internal/runtime/iframe-auth/identity.js.map +1 -0
  42. package/dist/internal/runtime/iframe-auth/index.d.ts +2 -0
  43. package/dist/internal/runtime/iframe-auth/index.js +3 -0
  44. package/dist/internal/runtime/iframe-auth/index.js.map +1 -0
  45. package/dist/internal/runtime/iframe-auth/sync.d.ts +2 -0
  46. package/dist/internal/runtime/iframe-auth/sync.js +23 -0
  47. package/dist/internal/runtime/iframe-auth/sync.js.map +1 -0
  48. package/dist/lib/measure.d.ts +21 -0
  49. package/dist/lib/measure.js +101 -0
  50. package/dist/lib/measure.js.map +1 -0
  51. package/dist/lib/platform.d.ts +2 -0
  52. package/dist/lib/platform.js +11 -0
  53. package/dist/lib/platform.js.map +1 -0
  54. package/dist/lib/utils.d.ts +2 -0
  55. package/dist/lib/utils.js +6 -0
  56. package/dist/lib/utils.js.map +1 -0
  57. package/dist/reference/llms.txt +36 -0
  58. package/dist/reference/sdk-api/build/taro/BuildContext.md +53 -0
  59. package/dist/reference/sdk-api/build/taro/CreateMicroappTaroConfigOptions.md +62 -0
  60. package/dist/reference/sdk-api/build/taro/createMicroappTaroConfig.md +66 -0
  61. package/dist/reference/sdk-api/build/taro/index.md +11 -0
  62. package/dist/reference/sdk-api/runtime/CreateMicroappClientOptions.md +47 -0
  63. package/dist/reference/sdk-api/runtime/createMicroappClient.md +378 -0
  64. package/dist/reference/sdk-api/runtime/index.md +10 -0
  65. package/dist/reference/sdk-api.json +1534 -0
  66. package/dist/reference/sdk-api.md +43 -0
  67. package/dist/runtime/client.d.ts +63 -0
  68. package/dist/runtime/client.js +194 -0
  69. package/dist/runtime/client.js.map +1 -0
  70. package/dist/runtime/closed-domain-request-header.d.ts +4 -0
  71. package/dist/runtime/closed-domain-request-header.js +8 -0
  72. package/dist/runtime/closed-domain-request-header.js.map +1 -0
  73. package/dist/runtime/default-client.d.ts +57 -0
  74. package/dist/runtime/default-client.js +21 -0
  75. package/dist/runtime/default-client.js.map +1 -0
  76. package/dist/runtime/default-iframe-auth.d.ts +8 -0
  77. package/dist/runtime/default-iframe-auth.js +10 -0
  78. package/dist/runtime/default-iframe-auth.js.map +1 -0
  79. package/dist/runtime/douyin-container-request.d.ts +11 -0
  80. package/dist/runtime/douyin-container-request.js +301 -0
  81. package/dist/runtime/douyin-container-request.js.map +1 -0
  82. package/dist/runtime/douyin-login-request.d.ts +32 -0
  83. package/dist/runtime/douyin-login-request.js +400 -0
  84. package/dist/runtime/douyin-login-request.js.map +1 -0
  85. package/dist/runtime/globals.d.ts +342 -0
  86. package/dist/runtime/index.d.ts +4 -0
  87. package/dist/runtime/index.js +4 -0
  88. package/dist/runtime/index.js.map +1 -0
  89. package/dist/runtime/network-url.d.ts +3 -0
  90. package/dist/runtime/network-url.js +53 -0
  91. package/dist/runtime/network-url.js.map +1 -0
  92. package/dist/types/taro.d.ts +1 -0
  93. package/dist/ui/accordion.d.ts +17 -0
  94. package/dist/ui/accordion.js +60 -0
  95. package/dist/ui/accordion.js.map +1 -0
  96. package/dist/ui/alert-dialog.d.ts +33 -0
  97. package/dist/ui/alert-dialog.js +96 -0
  98. package/dist/ui/alert-dialog.js.map +1 -0
  99. package/dist/ui/alert.d.ts +11 -0
  100. package/dist/ui/alert.js +49 -0
  101. package/dist/ui/alert.js.map +1 -0
  102. package/dist/ui/aspect-ratio.d.ts +5 -0
  103. package/dist/ui/aspect-ratio.js +10 -0
  104. package/dist/ui/aspect-ratio.js.map +1 -0
  105. package/dist/ui/avatar.d.ts +14 -0
  106. package/dist/ui/avatar.js +50 -0
  107. package/dist/ui/avatar.js.map +1 -0
  108. package/dist/ui/badge.d.ts +8 -0
  109. package/dist/ui/badge.js +27 -0
  110. package/dist/ui/badge.js.map +1 -0
  111. package/dist/ui/button-group.d.ts +14 -0
  112. package/dist/ui/button-group.js +52 -0
  113. package/dist/ui/button-group.js.map +1 -0
  114. package/dist/ui/button.d.ts +30 -0
  115. package/dist/ui/button.js +75 -0
  116. package/dist/ui/button.js.map +1 -0
  117. package/dist/ui/calendar.d.ts +29 -0
  118. package/dist/ui/calendar.js +141 -0
  119. package/dist/ui/calendar.js.map +1 -0
  120. package/dist/ui/card.d.ts +12 -0
  121. package/dist/ui/card.js +38 -0
  122. package/dist/ui/card.js.map +1 -0
  123. package/dist/ui/carousel.d.ts +30 -0
  124. package/dist/ui/carousel.js +60 -0
  125. package/dist/ui/carousel.js.map +1 -0
  126. package/dist/ui/checkbox.d.ts +9 -0
  127. package/dist/ui/checkbox.js +20 -0
  128. package/dist/ui/checkbox.js.map +1 -0
  129. package/dist/ui/collapsible.d.ts +18 -0
  130. package/dist/ui/collapsible.js +53 -0
  131. package/dist/ui/collapsible.js.map +1 -0
  132. package/dist/ui/combobox.d.ts +55 -0
  133. package/dist/ui/combobox.js +165 -0
  134. package/dist/ui/combobox.js.map +1 -0
  135. package/dist/ui/dialog.d.ts +26 -0
  136. package/dist/ui/dialog.js +54 -0
  137. package/dist/ui/dialog.js.map +1 -0
  138. package/dist/ui/drawer.d.ts +21 -0
  139. package/dist/ui/drawer.js +57 -0
  140. package/dist/ui/drawer.js.map +1 -0
  141. package/dist/ui/dropdown-menu.d.ts +52 -0
  142. package/dist/ui/dropdown-menu.js +112 -0
  143. package/dist/ui/dropdown-menu.js.map +1 -0
  144. package/dist/ui/empty.d.ts +12 -0
  145. package/dist/ui/empty.js +35 -0
  146. package/dist/ui/empty.js.map +1 -0
  147. package/dist/ui/field.d.ts +26 -0
  148. package/dist/ui/field.js +117 -0
  149. package/dist/ui/field.js.map +1 -0
  150. package/dist/ui/helpers.d.ts +6 -0
  151. package/dist/ui/helpers.js +23 -0
  152. package/dist/ui/helpers.js.map +1 -0
  153. package/dist/ui/index.d.ts +47 -0
  154. package/dist/ui/index.js +48 -0
  155. package/dist/ui/index.js.map +1 -0
  156. package/dist/ui/input-group.d.ts +17 -0
  157. package/dist/ui/input-group.js +122 -0
  158. package/dist/ui/input-group.js.map +1 -0
  159. package/dist/ui/input-otp.d.ts +18 -0
  160. package/dist/ui/input-otp.js +48 -0
  161. package/dist/ui/input-otp.js.map +1 -0
  162. package/dist/ui/input.d.ts +5 -0
  163. package/dist/ui/input.js +8 -0
  164. package/dist/ui/input.js.map +1 -0
  165. package/dist/ui/item.d.ts +22 -0
  166. package/dist/ui/item.js +83 -0
  167. package/dist/ui/item.js.map +1 -0
  168. package/dist/ui/label.d.ts +3 -0
  169. package/dist/ui/label.js +8 -0
  170. package/dist/ui/label.js.map +1 -0
  171. package/dist/ui/menubar.d.ts +65 -0
  172. package/dist/ui/menubar.js +244 -0
  173. package/dist/ui/menubar.js.map +1 -0
  174. package/dist/ui/navigation-menu.d.ts +27 -0
  175. package/dist/ui/navigation-menu.js +72 -0
  176. package/dist/ui/navigation-menu.js.map +1 -0
  177. package/dist/ui/pagination.d.ts +17 -0
  178. package/dist/ui/pagination.js +28 -0
  179. package/dist/ui/pagination.js.map +1 -0
  180. package/dist/ui/popover.d.ts +27 -0
  181. package/dist/ui/popover.js +139 -0
  182. package/dist/ui/popover.js.map +1 -0
  183. package/dist/ui/portal.d.ts +5 -0
  184. package/dist/ui/portal.js +18 -0
  185. package/dist/ui/portal.js.map +1 -0
  186. package/dist/ui/progress.d.ts +45 -0
  187. package/dist/ui/progress.js +67 -0
  188. package/dist/ui/progress.js.map +1 -0
  189. package/dist/ui/radio-group.d.ts +12 -0
  190. package/dist/ui/radio-group.js +29 -0
  191. package/dist/ui/radio-group.js.map +1 -0
  192. package/dist/ui/resizable.d.ts +20 -0
  193. package/dist/ui/resizable.js +244 -0
  194. package/dist/ui/resizable.js.map +1 -0
  195. package/dist/ui/scroll-area.d.ts +8 -0
  196. package/dist/ui/scroll-area.js +34 -0
  197. package/dist/ui/scroll-area.js.map +1 -0
  198. package/dist/ui/select.d.ts +35 -0
  199. package/dist/ui/select.js +136 -0
  200. package/dist/ui/select.js.map +1 -0
  201. package/dist/ui/separator.d.ts +5 -0
  202. package/dist/ui/separator.js +8 -0
  203. package/dist/ui/separator.js.map +1 -0
  204. package/dist/ui/sheet.d.ts +26 -0
  205. package/dist/ui/sheet.js +67 -0
  206. package/dist/ui/sheet.js.map +1 -0
  207. package/dist/ui/skeleton.d.ts +3 -0
  208. package/dist/ui/skeleton.js +8 -0
  209. package/dist/ui/skeleton.js.map +1 -0
  210. package/dist/ui/slider.d.ts +12 -0
  211. package/dist/ui/slider.js +94 -0
  212. package/dist/ui/slider.js.map +1 -0
  213. package/dist/ui/sonner.d.ts +6 -0
  214. package/dist/ui/sonner.js +13 -0
  215. package/dist/ui/sonner.js.map +1 -0
  216. package/dist/ui/spinner.d.ts +3 -0
  217. package/dist/ui/spinner.js +9 -0
  218. package/dist/ui/spinner.js.map +1 -0
  219. package/dist/ui/switch.d.ts +11 -0
  220. package/dist/ui/switch.js +33 -0
  221. package/dist/ui/switch.js.map +1 -0
  222. package/dist/ui/table.d.ts +13 -0
  223. package/dist/ui/table.js +54 -0
  224. package/dist/ui/table.js.map +1 -0
  225. package/dist/ui/tabs.d.ts +23 -0
  226. package/dist/ui/tabs.js +61 -0
  227. package/dist/ui/tabs.js.map +1 -0
  228. package/dist/ui/tailwind.css +2 -0
  229. package/dist/ui/textarea.d.ts +3 -0
  230. package/dist/ui/textarea.js +13 -0
  231. package/dist/ui/textarea.js.map +1 -0
  232. package/dist/ui/theme.css +234 -0
  233. package/dist/ui/toggle-group.d.ts +19 -0
  234. package/dist/ui/toggle-group.js +73 -0
  235. package/dist/ui/toggle-group.js.map +1 -0
  236. package/dist/ui/toggle.d.ts +14 -0
  237. package/dist/ui/toggle.js +41 -0
  238. package/dist/ui/toggle.js.map +1 -0
  239. package/package.json +97 -0
@@ -0,0 +1,69 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { readFileSync } from 'node:fs';
3
+ import path from 'node:path';
4
+ import eslint from '@eslint/js';
5
+ import importPlugin from 'eslint-plugin-import';
6
+ import globals from 'globals';
7
+ import tseslint from 'typescript-eslint';
8
+
9
+ export function createMicroappServerEslintConfig(options = {}) {
10
+ const serverRoot = path.resolve(options.tsconfigRootDir ?? process.cwd());
11
+ const dependencyManifestFingerprint = createHash('sha256')
12
+ .update(readFileSync(path.resolve(serverRoot, '../package.json')))
13
+ .update('\0')
14
+ .update(readFileSync(path.resolve(serverRoot, 'package.json')))
15
+ .digest('hex');
16
+ const defaults = tseslint.config(
17
+ {
18
+ ignores: ['eslint.config.mjs'],
19
+ },
20
+ eslint.configs.recommended,
21
+ ...tseslint.configs.recommendedTypeChecked,
22
+ {
23
+ languageOptions: {
24
+ globals: {
25
+ ...globals.node,
26
+ ...globals.jest,
27
+ },
28
+ sourceType: 'commonjs',
29
+ parserOptions: {
30
+ projectService: true,
31
+ tsconfigRootDir: serverRoot,
32
+ },
33
+ },
34
+ },
35
+ {
36
+ settings: {
37
+ 'microapp/dependency-manifest-fingerprint': dependencyManifestFingerprint,
38
+ },
39
+ plugins: {
40
+ import: importPlugin,
41
+ },
42
+ rules: {
43
+ 'import/no-extraneous-dependencies': [
44
+ 'error',
45
+ {
46
+ includeTypes: true,
47
+ packageDir: serverRoot,
48
+ },
49
+ ],
50
+ '@typescript-eslint/no-explicit-any': 'off',
51
+ '@typescript-eslint/no-floating-promises': 'warn',
52
+ '@typescript-eslint/no-unsafe-argument': 'off',
53
+ '@typescript-eslint/no-unsafe-assignment': 'off',
54
+ '@typescript-eslint/no-unsafe-member-access': 'off',
55
+ '@typescript-eslint/no-unsafe-call': 'off',
56
+ '@typescript-eslint/no-unsafe-return': 'off',
57
+ '@typescript-eslint/no-unused-vars': 'off',
58
+ '@typescript-eslint/require-await': 'off',
59
+ '@typescript-eslint/no-redundant-type-constituents': 'off',
60
+ },
61
+ },
62
+ );
63
+ const overrides = options.overrides;
64
+ if (!overrides) return defaults;
65
+ if (typeof overrides === 'function') return overrides(defaults) ?? defaults;
66
+ return tseslint.config(...defaults, ...(Array.isArray(overrides) ? overrides : [overrides]));
67
+ }
68
+
69
+ export default createMicroappServerEslintConfig
@@ -0,0 +1,553 @@
1
+ import eslint from '@eslint/js';
2
+ import { fixupPluginRules } from '@eslint/compat';
3
+ import tseslint from 'typescript-eslint';
4
+ import reactPlugin from 'eslint-plugin-react';
5
+ import reactHooksPlugin from 'eslint-plugin-react-hooks';
6
+ import importPlugin from 'eslint-plugin-import';
7
+ import globals from 'globals';
8
+ import microappPages from './eslint-plugin-microapp-pages.mjs';
9
+
10
+ const REMOTE_CSS_IMPORT_PATTERN =
11
+ /@import\s+(?:url\(\s*['"]?((?:https?:)?\/\/[^'")\s]+)['"]?\s*\)|['"]((?:https?:)?\/\/[^'"\s]+)['"])/g;
12
+ const CSS_FONT_SIZE_DECLARATION_PATTERN =
13
+ /(?:^|[;{\s])font-size\s*:\s*([^;{}]+)/gi;
14
+
15
+ /**
16
+ * 检测项目选定的 Lucide Taro 包导入的图标是否显式传了 color 属性。
17
+ * 小程序端图标通过 base64 SVG + <Image /> 渲染,无法继承 currentColor 或 CSS text-* 颜色,
18
+ * 未传 color 时笔画默认为黑色。
19
+ */
20
+ function createLucideColorCheckPlugin(importSources = ['@open-dy/lucide-taro']) {
21
+ const sources = new Set(
22
+ (Array.isArray(importSources) ? importSources : [importSources])
23
+ .filter((source) => typeof source === 'string' && source.length > 0),
24
+ )
25
+ const label = [...sources].join(' / ') || '@open-dy/lucide-taro'
26
+
27
+ return {
28
+ rules: {
29
+ 'require-lucide-color': {
30
+ create(context) {
31
+ const lucideImports = new Set();
32
+
33
+ return {
34
+ ImportDeclaration(node) {
35
+ if (sources.has(node.source.value)) {
36
+ for (const specifier of node.specifiers) {
37
+ if (specifier.type === 'ImportSpecifier') {
38
+ lucideImports.add(specifier.local.name);
39
+ }
40
+ }
41
+ }
42
+ },
43
+ JSXOpeningElement(node) {
44
+ const name =
45
+ node.name.type === 'JSXIdentifier' ? node.name.name : null;
46
+ if (!name || !lucideImports.has(name)) return;
47
+
48
+ const hasColor = node.attributes.some(
49
+ attr =>
50
+ attr.type === 'JSXAttribute' &&
51
+ attr.name &&
52
+ attr.name.name === 'color'
53
+ );
54
+
55
+ if (!hasColor) {
56
+ context.report({
57
+ node,
58
+ message: `${label} 规范:<${name}> 缺少 color 属性。小程序端图标通过 <Image /> 渲染,无法继承父级颜色,未传 color 时笔画默认为黑色。请显式传入,如 color="#6366f1"。`,
59
+ });
60
+ }
61
+ },
62
+ };
63
+ },
64
+ },
65
+ },
66
+ }
67
+ }
68
+
69
+ const cssImportGuardPlugin = {
70
+ processors: {
71
+ css: {
72
+ preprocess(text) {
73
+ const lines = text.replace(/\/\*[\s\S]*?\*\//g, comment => {
74
+ if (comment.includes('eslint-')) return comment;
75
+ return comment.replace(/[^\n]/g, ' ');
76
+ }).split('\n');
77
+ const virtualLines = lines.map(line => {
78
+ const externalImportCalls = [...line.matchAll(REMOTE_CSS_IMPORT_PATTERN)]
79
+ .map(match => {
80
+ const url = match[1] ?? match[2];
81
+
82
+ return `__cssExternalImport(${JSON.stringify(url)});`;
83
+ });
84
+
85
+ const arbitraryFontSizeCalls = [...line.matchAll(CSS_FONT_SIZE_DECLARATION_PATTERN)]
86
+ .map(match => match[1].trim())
87
+ .filter(isArbitraryFontSizeValue)
88
+ .map(value => `__cssArbitraryFontSize(${JSON.stringify(value)});`);
89
+
90
+ if (/eslint-(?:disable|enable)/.test(line)) {
91
+ return [
92
+ line.trim(),
93
+ ...externalImportCalls,
94
+ ...arbitraryFontSizeCalls,
95
+ ].join(' ');
96
+ }
97
+
98
+ return [
99
+ ...externalImportCalls,
100
+ ...arbitraryFontSizeCalls,
101
+ ].join(' ');
102
+ });
103
+
104
+ return [virtualLines.join('\n')];
105
+ },
106
+ postprocess(messages) {
107
+ return messages.flat();
108
+ },
109
+ supportsAutofix: false,
110
+ },
111
+ },
112
+ };
113
+
114
+ function isArbitraryFontSizeValue(value) {
115
+ const normalized = value
116
+ .replace(/\s*!important\s*$/i, '')
117
+ .trim();
118
+
119
+ return ARBITRARY_FONT_SIZE_VALUE_PATTERN.test(normalized);
120
+ }
121
+
122
+ const baseRestrictedSyntaxRules = [
123
+ {
124
+ selector: "CallExpression[callee.name='require']",
125
+ message:
126
+ "工程规范:前端 src 目录使用 ES Module,禁止使用 require()",
127
+ },
128
+ {
129
+ selector: "MemberExpression[object.name='process'][property.name='env']",
130
+ message:
131
+ '工程规范:请勿在 src 目录下直接使用 process.env\n如需获取 URL 请求前缀,请使用已经注入全局的 PROJECT_DOMAIN',
132
+ },
133
+ {
134
+ selector:
135
+ ":matches(ExportNamedDeclaration, ExportDefaultDeclaration) :matches([id.name='Network'], [declaration.id.name='Network'])",
136
+ message:
137
+ "工程规范:禁止自行定义 Network,项目已提供 src/network.ts,请直接使用: import { Network } from '@/network'",
138
+ },
139
+ {
140
+ selector:
141
+ "CallExpression[callee.name='__cssExternalImport'] > Literal[value=/^(?:https?:)?\\/\\//]",
142
+ message:
143
+ '抖音小程序兼容性:禁止在 CSS/TTSS 中使用远程 @import(如 Google Fonts)。请改为本地静态资源或删除该导入。',
144
+ },
145
+ {
146
+ selector:
147
+ "JSXAttribute[name.name='color'][value.type='Literal'][value.value='currentColor'], JSXAttribute[name.name='color'] > JSXExpressionContainer > Literal[value='currentColor']",
148
+ message:
149
+ '图标组件规范:禁止使用 color="currentColor",小程序端不会按预期继承颜色。请改为显式颜色值,或通过 LucideProvider 提供默认颜色。',
150
+ },
151
+ {
152
+ selector:
153
+ "ImportDeclaration[source.value='@tarojs/taro'] > ImportSpecifier[imported.name='Taro']",
154
+ message:
155
+ "Taro 导入规范:禁止 `import { Taro } from '@tarojs/taro'`。前端 tsconfig 未开启 esModuleInterop,tsc 会报 TS2596。请使用默认导入:`import Taro from '@tarojs/taro'`;需要 Hook 时写成 `import Taro, { useDidShow } from '@tarojs/taro'`。",
156
+ },
157
+ {
158
+ selector:
159
+ "ImportDeclaration[source.value='@tarojs/taro'] > ImportNamespaceSpecifier",
160
+ message:
161
+ "Taro 导入规范:禁止 `import * as Taro from '@tarojs/taro'`。请使用默认导入:`import Taro from '@tarojs/taro'`。",
162
+ },
163
+ ];
164
+
165
+ function createPageRestrictedSyntaxRules(
166
+ preferredUiImportBase = '@open-dy/vibecoding-sdk-taro/ui',
167
+ ) {
168
+ return [
169
+ ['Button', 'button'],
170
+ ['Input', 'input'],
171
+ ['Textarea', 'textarea'],
172
+ ['Label', 'label'],
173
+ ['Switch', 'switch'],
174
+ ['Slider', 'slider'],
175
+ ['Progress', 'progress'],
176
+ ].map(([component, module]) => ({
177
+ selector:
178
+ `ImportDeclaration[source.value='@tarojs/components'] ImportSpecifier[imported.name='${component}']`,
179
+ message:
180
+ `组件规范:${component} 优先使用 '${preferredUiImportBase}/${module}',` +
181
+ `不要在页面中直接使用 '@tarojs/components' 的 ${component}。`,
182
+ }))
183
+ }
184
+
185
+ const ARBITRARY_FONT_SIZE_CLASS_PATTERN =
186
+ /^(?:!)?text-\[(?:length:)?(?:(?:\d+(?:\.\d+)?|\.\d+)(?:px|rpx|rem|em|vw|vh)|calc\([^\]]+\)|clamp\([^\]]+\)|min\([^\]]+\)|max\([^\]]+\))(?:\/[^\]]+)?\]$/;
187
+ const ARBITRARY_FONT_SIZE_VALUE_PATTERN =
188
+ /^(?:(?:\d+(?:\.\d+)?|\.\d+)(?:px|rpx|rem|em|vw|vh)|calc\([^)]+\)|clamp\([^)]+\)|min\([^)]+\)|max\([^)]+\))$/i;
189
+
190
+ function splitTailwindClassToken(token) {
191
+ let bracketDepth = 0;
192
+ let lastSeparatorIndex = -1;
193
+
194
+ for (let index = 0; index < token.length; index += 1) {
195
+ const char = token[index];
196
+
197
+ if (char === '[') bracketDepth += 1;
198
+ if (char === ']') bracketDepth -= 1;
199
+ if (char === ':' && bracketDepth === 0) lastSeparatorIndex = index;
200
+ }
201
+
202
+ return lastSeparatorIndex >= 0
203
+ ? token.slice(lastSeparatorIndex + 1)
204
+ : token;
205
+ }
206
+
207
+ function collectStaticStrings(node, result = []) {
208
+ if (!node) return result;
209
+
210
+ if (node.type === 'Literal' && typeof node.value === 'string') {
211
+ result.push(node.value);
212
+ return result;
213
+ }
214
+
215
+ if (node.type === 'TemplateLiteral') {
216
+ for (const quasi of node.quasis) {
217
+ if (quasi.value.cooked) result.push(quasi.value.cooked);
218
+ }
219
+
220
+ for (const expression of node.expressions) {
221
+ collectStaticStrings(expression, result);
222
+ }
223
+
224
+ return result;
225
+ }
226
+
227
+ for (const key of [
228
+ 'left',
229
+ 'right',
230
+ 'argument',
231
+ 'callee',
232
+ 'test',
233
+ 'consequent',
234
+ 'alternate',
235
+ 'object',
236
+ 'property',
237
+ ]) {
238
+ collectStaticStrings(node[key], result);
239
+ }
240
+
241
+ for (const key of ['arguments', 'elements', 'expressions']) {
242
+ if (Array.isArray(node[key])) {
243
+ for (const child of node[key]) collectStaticStrings(child, result);
244
+ }
245
+ }
246
+
247
+ return result;
248
+ }
249
+
250
+ const tailwindEnforcementPlugin = {
251
+ rules: {
252
+ 'no-arbitrary-font-size': {
253
+ create(context) {
254
+ function reportArbitraryFontSize(node, className) {
255
+ const violating = className
256
+ .split(/\s+/)
257
+ .map(token => token.trim())
258
+ .filter(Boolean)
259
+ .filter(token => ARBITRARY_FONT_SIZE_CLASS_PATTERN.test(splitTailwindClassToken(token)));
260
+
261
+ if (violating.length === 0) return;
262
+
263
+ context.report({
264
+ node,
265
+ message:
266
+ `字体规范:除非特殊情况,避免使用任意字体大小类 [${violating.join(', ')}]。` +
267
+ '请改用 Tailwind 标准字号,如 text-xs、text-sm、text-base、text-lg,避免小程序/H5 端单位转换不一致。',
268
+ });
269
+ }
270
+
271
+ function reportCssArbitraryFontSize(node, value) {
272
+ context.report({
273
+ node,
274
+ message:
275
+ `字体规范:除非特殊情况,避免在样式文件中直接声明 font-size: ${value}。` +
276
+ '请优先使用 Tailwind 标准字号类,如 text-xs、text-sm、text-base、text-lg,避免小程序/H5 端单位转换不一致。',
277
+ });
278
+ }
279
+
280
+ return {
281
+ JSXAttribute(node) {
282
+ if (node.name?.name !== 'className') return;
283
+
284
+ if (node.value?.type === 'Literal' && typeof node.value.value === 'string') {
285
+ reportArbitraryFontSize(node, node.value.value);
286
+ return;
287
+ }
288
+
289
+ if (node.value?.type !== 'JSXExpressionContainer') return;
290
+
291
+ for (const className of collectStaticStrings(node.value.expression)) {
292
+ reportArbitraryFontSize(node, className);
293
+ }
294
+ },
295
+ CallExpression(node) {
296
+ if (node.callee?.name !== '__cssArbitraryFontSize') return;
297
+
298
+ const [valueNode] = node.arguments;
299
+ const value = valueNode?.value;
300
+
301
+ reportCssArbitraryFontSize(
302
+ node,
303
+ typeof value === 'string' ? value : '任意字号'
304
+ );
305
+ },
306
+ };
307
+ },
308
+ },
309
+ },
310
+ };
311
+
312
+ const pageRestrictedCssImportPatterns = [
313
+ {
314
+ group: [
315
+ '*.css',
316
+ '**/*.css',
317
+ '*.scss',
318
+ '**/*.scss',
319
+ '*.less',
320
+ '**/*.less',
321
+ '*.sass',
322
+ '**/*.sass',
323
+ ],
324
+ message:
325
+ '样式规范:页面中禁止直接 import CSS/SCSS 文件,请使用 Tailwind className 实现样式。' +
326
+ '仅在 Tailwind 明显无法满足(如复杂关键帧动画)时才创建页面级样式文件,且范围须最小化。',
327
+ },
328
+ ];
329
+
330
+ const TARO_NATIVE_SVG_ELEMENTS = [
331
+ 'svg',
332
+ 'circle',
333
+ 'path',
334
+ 'rect',
335
+ 'line',
336
+ 'polyline',
337
+ 'polygon',
338
+ 'ellipse',
339
+ 'g',
340
+ 'defs',
341
+ 'clipPath',
342
+ 'linearGradient',
343
+ 'radialGradient',
344
+ 'stop',
345
+ 'mask',
346
+ 'pattern',
347
+ 'textPath',
348
+ 'use',
349
+ ];
350
+
351
+ const indexPageRestrictedSyntaxRules = [
352
+ {
353
+ selector: 'JSXText[value=/\\s*应用开发中\\s*/]',
354
+ message:
355
+ '工程规范:检测到首页 (src/pages/index/index.tsx) 仍为默认占位页面,这会导致用户无法进入新增页面,请根据用户需求开发实际的首页功能与界面。如果已经开发了新的首页,也需要删除旧首页,并更新 src/app.config.ts 文件',
356
+ },
357
+ ];
358
+
359
+ export function createMicroappTaroEslintConfig(options = {}) {
360
+ const lucideColorCheckPlugin = createLucideColorCheckPlugin(options.lucideImportSources)
361
+ const pageRestrictedSyntaxRules = createPageRestrictedSyntaxRules(
362
+ options.preferredUiImportBase,
363
+ )
364
+ const defaults = tseslint.config(
365
+ {
366
+ ignores: ['eslint.config.mjs', 'dist/**', 'dist-*/**', 'node_modules/**', 'src/components/sar-game/**'],
367
+ },
368
+ eslint.configs.recommended,
369
+ ...tseslint.configs.recommended,
370
+ {
371
+ languageOptions: {
372
+ globals: {
373
+ ...globals.browser,
374
+ ...globals.node,
375
+ ...globals.es2021,
376
+ },
377
+ parserOptions: {
378
+ ecmaFeatures: { jsx: true },
379
+ sourceType: 'module',
380
+ },
381
+ },
382
+ settings: {
383
+ react: {
384
+ pragma: 'React',
385
+ version: 'detect',
386
+ },
387
+ 'import/resolver': {
388
+ typescript: {
389
+ alwaysTryTypes: true,
390
+ project: './tsconfig.json',
391
+ },
392
+ },
393
+ 'import/core-modules': ['@tarojs/taro', '@tarojs/components'],
394
+ },
395
+ plugins: {
396
+ react: fixupPluginRules(reactPlugin),
397
+ 'react-hooks': fixupPluginRules(reactHooksPlugin),
398
+ import: fixupPluginRules(importPlugin),
399
+ },
400
+ rules: {
401
+ 'react-hooks/rules-of-hooks': 'error',
402
+ 'react-hooks/exhaustive-deps': 'warn',
403
+ 'react/jsx-key': 'warn',
404
+ 'react/jsx-no-duplicate-props': ['error', { ignoreCase: true }],
405
+ 'react/jsx-no-undef': 'error',
406
+ 'react/jsx-uses-vars': 'error',
407
+ 'react/jsx-uses-react': 'off',
408
+ 'react/react-in-jsx-scope': 'off',
409
+ 'react/no-children-prop': 'error',
410
+ 'react/no-direct-mutation-state': 'error',
411
+ 'react/no-string-refs': 'error',
412
+ 'react/require-render-return': 'error',
413
+ 'react/no-danger-with-children': 'error',
414
+ 'react/jsx-no-leaked-render': ['error', { validStrategies: ['ternary', 'coerce'] }],
415
+
416
+ 'import/export': 'error',
417
+ 'import/no-duplicates': 'error',
418
+
419
+ 'no-undef': 'off',
420
+ '@typescript-eslint/no-explicit-any': 'off',
421
+ '@typescript-eslint/no-unused-vars': 'off',
422
+ '@typescript-eslint/no-require-imports': 'off',
423
+ '@typescript-eslint/no-namespace': 'off',
424
+
425
+ 'react/forbid-elements': [
426
+ 'error',
427
+ {
428
+ forbid: [
429
+ { element: 'select', message: '请使用 Picker 组件代替 <select>' },
430
+ ...TARO_NATIVE_SVG_ELEMENTS.map(element => ({
431
+ element,
432
+ message:
433
+ `抖音小程序兼容性:禁止使用原生 <${element}> SVG 标签。` +
434
+ '请优先用 View + Tailwind/CSS 实现;其次使用 Image、本地静态资源或项目已适配的 @open-dy/lucide-taro 图标组件;复杂动态绘制才考虑 Canvas。',
435
+ })),
436
+ ],
437
+ },
438
+ ],
439
+ 'tailwindcss/classnames-order': 'off',
440
+ 'tailwindcss/no-custom-classname': 'off',
441
+ },
442
+ },
443
+ {
444
+ files: ['src/**/*.{js,jsx,ts,tsx}'],
445
+ ignores: ['src/network.ts'],
446
+ plugins: {
447
+ lucide: lucideColorCheckPlugin,
448
+ microappPages,
449
+ tailwind: tailwindEnforcementPlugin,
450
+ },
451
+ rules: {
452
+ 'microappPages/nav-url-in-app-pages': 'error',
453
+ // 'microappPages/page-dirs-in-app-pages': 'error',
454
+ 'microappPages/declared-pages-must-exist': 'error',
455
+ 'microappPages/no-screen-height-in-tabbar-page': 'error',
456
+ 'lucide/require-lucide-color': 'error',
457
+ 'tailwind/no-arbitrary-font-size': 'error',
458
+ '@typescript-eslint/no-require-imports': 'error',
459
+ 'no-restricted-syntax': ['error', ...baseRestrictedSyntaxRules],
460
+ 'no-restricted-globals': [
461
+ 'error',
462
+ {
463
+ name: 'fetch',
464
+ message:
465
+ '工程规范:禁止直接使用 fetch API,请使用 network.ts 中的 Network.request 方法来发起网络请求。',
466
+ },
467
+ ],
468
+ 'no-restricted-properties': [
469
+ 'error',
470
+ {
471
+ object: 'window',
472
+ property: 'fetch',
473
+ message:
474
+ '工程规范:禁止直接使用 window.fetch API,请使用 network.ts 中的 Network.request 方法来发起网络请求。',
475
+ },
476
+ {
477
+ object: 'Taro',
478
+ property: 'request',
479
+ message:
480
+ "工程规范:请使用 Network.request 替代 Taro.request,导入方式: import { Network } from '@/network'",
481
+ },
482
+ {
483
+ object: 'Taro',
484
+ property: 'uploadFile',
485
+ message:
486
+ "工程规范:请使用 Network.uploadFile 替代 Taro.uploadFile,导入方式: import { Network } from '@/network'",
487
+ },
488
+ {
489
+ object: 'Taro',
490
+ property: 'downloadFile',
491
+ message:
492
+ "工程规范:请使用 Network.downloadFile 替代 Taro.downloadFile,导入方式: import { Network } from '@/network'",
493
+ },
494
+ {
495
+ object: 'Taro',
496
+ property: 'getWindowInfo',
497
+ message:
498
+ "工程规范:请使用 Taro.getSystemInfoSync 替代 Taro.getWindowInfo",
499
+ },
500
+ ],
501
+ },
502
+ },
503
+ {
504
+ files: ['src/**/*.{css,scss}'],
505
+ plugins: {
506
+ local: cssImportGuardPlugin,
507
+ tailwind: tailwindEnforcementPlugin,
508
+ },
509
+ processor: 'local/css',
510
+ rules: {
511
+ 'no-undef': 'off',
512
+ 'tailwind/no-arbitrary-font-size': 'error',
513
+ 'no-restricted-syntax': ['error', ...baseRestrictedSyntaxRules],
514
+ },
515
+ },
516
+ {
517
+ files: ['src/components/ui/**/*.tsx'],
518
+ rules: {
519
+ 'lucide/require-lucide-color': 'off',
520
+ },
521
+ },
522
+ {
523
+ files: ['src/pages/**/*.tsx'],
524
+ rules: {
525
+ 'no-restricted-syntax': [
526
+ 'error',
527
+ ...baseRestrictedSyntaxRules,
528
+ ...pageRestrictedSyntaxRules,
529
+ ],
530
+ 'no-restricted-imports': ['warn', { patterns: pageRestrictedCssImportPatterns }],
531
+ },
532
+ },
533
+ {
534
+ files: ['src/pages/index/index.tsx'],
535
+ rules: {
536
+ 'no-restricted-syntax': [
537
+ 'error',
538
+ ...baseRestrictedSyntaxRules,
539
+ ...pageRestrictedSyntaxRules,
540
+ ...indexPageRestrictedSyntaxRules,
541
+ ],
542
+ 'no-restricted-imports': ['warn', { patterns: pageRestrictedCssImportPatterns }],
543
+ },
544
+ },
545
+ );
546
+
547
+ const overrides = options.overrides
548
+ if (!overrides) return defaults
549
+ if (typeof overrides === 'function') return overrides(defaults) ?? defaults
550
+ return tseslint.config(...defaults, ...(Array.isArray(overrides) ? overrides : [overrides]))
551
+ }
552
+
553
+ export default createMicroappTaroEslintConfig
@@ -0,0 +1,2 @@
1
+ export * from './runtime.js';
2
+ export * from './build.js';
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './runtime.js';
2
+ export * from './build.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,SAAS,CAAA"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * 抖音 Button openType 扩展。上游 Taro 类型未声明这些字段,但 TT 运行时支持。
3
+ * 保持为 module,确保 declare module 与官方 Button 类型合并而不是覆盖。
4
+ */
5
+ import "@tarojs/components";
6
+
7
+ export {};
8
+
9
+ declare global {
10
+ type DouyinOpenTypeDetailEvent = {
11
+ detail?: { errMsg?: string; errNo?: number };
12
+ };
13
+
14
+ type DouyinOpenButtonExtras = {
15
+ hideBorder?: boolean;
16
+ dataVideoId?: string;
17
+ dataVideoType?: string;
18
+ dataChannel?: string;
19
+ "data-video-id"?: string;
20
+ "data-video-type"?: string;
21
+ "data-channel"?: string;
22
+ onNavigateToVideoView?: (event: DouyinOpenTypeDetailEvent) => void;
23
+ onAddShortcut?: (event: DouyinOpenTypeDetailEvent) => void;
24
+ };
25
+ }
26
+
27
+ declare module "@tarojs/components/types/Button" {
28
+ interface ButtonProps extends DouyinOpenButtonExtras {}
29
+ }
@@ -0,0 +1,20 @@
1
+ export type IframeTaroRuntime = {
2
+ getEnv?: () => unknown;
3
+ ENV_TYPE?: {
4
+ WEB?: unknown;
5
+ };
6
+ };
7
+ type IframeIdentity = {
8
+ accessToken: string;
9
+ expiresAt: number;
10
+ openId: string;
11
+ };
12
+ export declare const getIframeIdentity: (taro?: IframeTaroRuntime | null) => IframeIdentity | null;
13
+ export declare const persistIframeIdentity: (taro: IframeTaroRuntime | null | undefined, identity: IframeIdentity) => void;
14
+ export declare const clearIframeIdentity: (taro?: IframeTaroRuntime | null) => void;
15
+ export declare const getIframeIdentityHeaders: (taro?: IframeTaroRuntime | null) => Record<string, string>;
16
+ export declare const mergeIframeIdentityHeaders: (taro: IframeTaroRuntime | null | undefined, header?: Record<string, unknown>) => Record<string, unknown> | undefined;
17
+ export declare const parseIframeIdentityMessage: (taro: IframeTaroRuntime | null | undefined, event: MessageEvent<unknown>) => IframeIdentity | null;
18
+ export declare const isIframeLogoutMessage: (taro: IframeTaroRuntime | null | undefined, event: MessageEvent<unknown>) => boolean;
19
+ export declare const shouldListenIframeIdentityMessage: (taro?: IframeTaroRuntime | null) => boolean;
20
+ export {};