openyida 2026.7.7 → 2026.7.8

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 (63) hide show
  1. package/README.md +4 -2
  2. package/bin/yida.js +4 -4
  3. package/lib/app/canvas-compile.js +303 -0
  4. package/lib/app/publish.js +190 -39
  5. package/lib/auth/auth.js +11 -3
  6. package/lib/auth/login.js +34 -15
  7. package/lib/core/command-manifest.js +1 -1
  8. package/lib/core/env.js +19 -4
  9. package/lib/core/locales/ar.js +6 -2
  10. package/lib/core/locales/de.js +6 -2
  11. package/lib/core/locales/en.js +7 -3
  12. package/lib/core/locales/es.js +6 -2
  13. package/lib/core/locales/fr.js +6 -2
  14. package/lib/core/locales/hi.js +6 -2
  15. package/lib/core/locales/ja.js +7 -3
  16. package/lib/core/locales/ko.js +6 -2
  17. package/lib/core/locales/pt.js +6 -2
  18. package/lib/core/locales/vi.js +6 -2
  19. package/lib/core/locales/zh-HK.js +7 -3
  20. package/lib/core/locales/zh.js +7 -3
  21. package/lib/core/utils.js +195 -15
  22. package/lib/samples/yida-custom-page/custom-page-template.js +6 -6
  23. package/lib/samples/yida-custom-page/design-tokens.js +14 -12
  24. package/package.json +1 -1
  25. package/scripts/e2e-real/skill-coverage.js +4 -0
  26. package/scripts/validate-ci.sh +6 -0
  27. package/scripts/validate-package-size.js +12 -1
  28. package/yida-skills/SKILL.md +19 -5
  29. package/yida-skills/references/development-rules.md +2 -2
  30. package/yida-skills/references/field-and-url-reference.md +14 -1
  31. package/yida-skills/skills/yida-app/SKILL.md +3 -2
  32. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +113 -0
  33. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-authoring-examples.md +163 -0
  34. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-design-system.md +148 -0
  35. package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +115 -0
  36. package/yida-skills/skills/yida-canvas-custom-page/references/dependencies-and-cdn.md +45 -0
  37. package/yida-skills/skills/yida-canvas-custom-page/references/employeefield-verification.md +68 -0
  38. package/yida-skills/skills/yida-canvas-upgrade/SKILL.md +99 -0
  39. package/yida-skills/skills/yida-canvas-upgrade/references/migration-examples.md +69 -0
  40. package/yida-skills/skills/yida-custom-page/SKILL.md +7 -2
  41. package/yida-skills/skills/yida-custom-page/examples/attachment-upload.js +1 -1
  42. package/yida-skills/skills/yida-custom-page/references/coding-guide.md +3 -3
  43. package/yida-skills/skills/yida-custom-page/references/component-jsx-guide.md +3 -2
  44. package/yida-skills/skills/yida-custom-page/references/design-system.md +30 -13
  45. package/yida-skills/skills/yida-nav-shell/SKILL.md +119 -0
  46. package/yida-skills/skills/yida-nav-shell/references/nav-shell-patterns.md +302 -0
  47. package/yida-skills/skills/yida-page-config/SKILL.md +1 -0
  48. package/yida-skills/skills/yida-page-uiux/SKILL.md +68 -0
  49. package/yida-skills/skills/yida-page-uiux/references/scenes/dashboard.md +128 -0
  50. package/yida-skills/skills/yida-page-uiux/references/scenes/detail.md +79 -0
  51. package/yida-skills/skills/yida-page-uiux/references/scenes/landing.md +101 -0
  52. package/yida-skills/skills/yida-page-uiux/references/scenes/list.md +78 -0
  53. package/yida-skills/skills/yida-page-uiux/references/scenes/workbench.md +74 -0
  54. package/yida-skills/skills/yida-page-uiux/references/visual-decision-engine.md +151 -0
  55. package/yida-skills/skills/yida-page-uiux/workflow/output-decision-block.md +36 -0
  56. package/yida-skills/skills/yida-page-uiux/workflow/step-0-nav-shape.md +39 -0
  57. package/yida-skills/skills/yida-page-uiux/workflow/step-1-page-type.md +25 -0
  58. package/yida-skills/skills/yida-page-uiux/workflow/step-2-intent-decode.md +25 -0
  59. package/yida-skills/skills/yida-page-uiux/workflow/step-3-scene-routing.md +29 -0
  60. package/yida-skills/skills/yida-page-uiux/workflow/step-4-visual-decision.md +32 -0
  61. package/yida-skills/skills/yida-page-uiux/workflow/step-5-icon-and-assets.md +36 -0
  62. package/yida-skills/skills/yida-page-uiux/workflow/step-6-deai-selfcheck.md +37 -0
  63. package/yida-skills/skills/yida-publish-page/SKILL.md +7 -3
package/lib/auth/auth.js CHANGED
@@ -32,6 +32,13 @@ const { t } = require('../core/i18n');
32
32
 
33
33
  const AUTH_CACHE_FILE = '.cache/auth.json';
34
34
 
35
+ function maskIdentifier(value) {
36
+ const text = String(value || '');
37
+ if (!text) {return null;}
38
+ if (text.length <= 8) {return `${text.slice(0, 2)}***${text.slice(-1)}`;}
39
+ return `${text.slice(0, 4)}***${text.slice(-4)}`;
40
+ }
41
+
35
42
  // ── 配置读取 ──────────────────────────────────────────
36
43
 
37
44
  function loadAuthConfig() {
@@ -90,6 +97,7 @@ function authStatus() {
90
97
  const userId = cookieData.user_id || cookieData.userId || cookieData.staffId || cookieInfo.userId;
91
98
  const baseUrl = resolveBaseUrl(cookieData);
92
99
  const authConfig = loadAuthConfig();
100
+ const isEnvAuth = cookieData.auth_source === 'env';
93
101
 
94
102
  if (!csrfToken) {
95
103
  warn(t('auth.no_csrf_token'), false);
@@ -105,12 +113,12 @@ function authStatus() {
105
113
  chalkSuccess(t('auth.logged_in'), false);
106
114
  label('Base URL', baseUrl, { stderr: false });
107
115
  if (corpId) {
108
- label('Corp ID', corpId, { stderr: false });
116
+ label('Corp ID', isEnvAuth ? maskIdentifier(corpId) : corpId, { stderr: false });
109
117
  }
110
118
  if (userId) {
111
- label('User ID', userId, { stderr: false });
119
+ label('User ID', isEnvAuth ? maskIdentifier(userId) : userId, { stderr: false });
112
120
  }
113
- label('CSRF', `${csrfToken.slice(0, 16)}…`, { stderr: false });
121
+ label('CSRF', isEnvAuth ? '<redacted>' : `${csrfToken.slice(0, 16)}…`, { stderr: false });
114
122
 
115
123
  // 显示登录信息
116
124
  if (authConfig) {
package/lib/auth/login.js CHANGED
@@ -27,7 +27,8 @@ const {
27
27
  loadCookieData,
28
28
  resolveBaseUrl,
29
29
  detectActiveTool,
30
- isInjectedAuthMode,
30
+ isEnvAuthMode,
31
+ getLastEnvAuthError,
31
32
  } = require('../core/utils');
32
33
  const { t } = require('../core/i18n');
33
34
 
@@ -48,6 +49,9 @@ function loadConfig() {
48
49
  // ── Cookie 持久化 ─────────────────────────────────────
49
50
 
50
51
  function saveCookieCache(cookies, baseUrl) {
52
+ if (isEnvAuthMode()) {
53
+ return;
54
+ }
51
55
  const projectRoot = findProjectRoot();
52
56
  const cacheDir = path.join(projectRoot, '.cache');
53
57
 
@@ -61,6 +65,13 @@ function saveCookieCache(cookies, baseUrl) {
61
65
  process.stderr.write(` ${c.green}✔${c.reset} Cookie saved to ${c.dim}${cookieFile}${c.reset}\n`);
62
66
  }
63
67
 
68
+ function maskIdentifier(value) {
69
+ const text = String(value || '');
70
+ if (!text) {return null;}
71
+ if (text.length <= 8) {return `${text.slice(0, 2)}***${text.slice(-1)}`;}
72
+ return `${text.slice(0, 4)}***${text.slice(-4)}`;
73
+ }
74
+
64
75
  // ── 仅检查登录态 ──────────────────────────────────────
65
76
 
66
77
  /**
@@ -79,9 +90,12 @@ function checkLoginOnly(options = {}) {
79
90
  const legacyCookieFile = path.join(projectRoot, '.cache', 'cookies.json');
80
91
  const cookieData = loadCookieData(projectRoot);
81
92
  const cookies = cookieData && Array.isArray(cookieData.cookies) ? cookieData.cookies : [];
82
- const authMode = isInjectedAuthMode() ? 'injected' : 'default';
93
+ const envAuthError = getLastEnvAuthError();
94
+ const isEnvAuth = !!(cookieData && cookieData.auth_source === 'env');
95
+ const authMode = isEnvAuth || isEnvAuthMode() ? 'env' : 'default';
83
96
  const baseDiagnostics = {
84
97
  authMode,
98
+ authSource: authMode === 'env' ? 'env' : 'cache',
85
99
  activeTool: activeTool ? activeTool.tool : null,
86
100
  isWukong: !!(activeTool && activeTool.tool === 'wukong'),
87
101
  projectRoot,
@@ -106,10 +120,12 @@ function checkLoginOnly(options = {}) {
106
120
  corp_id_found: false,
107
121
  user_id_found: false,
108
122
  base_url_found: false,
109
- failure_reason: baseDiagnostics.cookieFileFound ? 'cookie_cache_unreadable_or_invalid' : 'cookie_cache_missing',
123
+ failure_reason: envAuthError
124
+ ? envAuthError.failure_reason
125
+ : (baseDiagnostics.cookieFileFound ? 'cookie_cache_unreadable_or_invalid' : 'cookie_cache_missing'),
110
126
  },
111
- message: authMode === 'injected'
112
- ? 'No injected Cookie cache, host page refresh required'
127
+ message: authMode === 'env'
128
+ ? 'No env Cookie, host page refresh required'
113
129
  : 'No local Cookie cache, QR scan login required',
114
130
  };
115
131
  }
@@ -119,6 +135,9 @@ function checkLoginOnly(options = {}) {
119
135
  const corpId = cookieData.corp_id || cookieData.corpId || cookieInfo.corpId;
120
136
  const userId = cookieData.user_id || cookieData.userId || cookieData.staffId || cookieInfo.userId;
121
137
  const baseUrl = resolveBaseUrl(cookieData);
138
+ const canIncludeSecrets = includeSecrets && !isEnvAuth;
139
+ const outputCorpId = isEnvAuth ? maskIdentifier(corpId) : corpId;
140
+ const outputUserId = isEnvAuth ? maskIdentifier(userId) : userId;
122
141
  const diagnostics = {
123
142
  ...baseDiagnostics,
124
143
  cache_readable: true,
@@ -136,8 +155,8 @@ function checkLoginOnly(options = {}) {
136
155
  status: 'not_logged_in',
137
156
  can_auto_use: false,
138
157
  diagnostics,
139
- message: authMode === 'injected'
140
- ? 'No csrf_token in injected Cookie cache, host page refresh required'
158
+ message: authMode === 'env'
159
+ ? 'No csrf_token in env Cookie, host page refresh required'
141
160
  : 'No tianshu_csrf_token in Cookie, re-login required',
142
161
  };
143
162
  }
@@ -145,15 +164,15 @@ function checkLoginOnly(options = {}) {
145
164
  const result = {
146
165
  status: 'ok',
147
166
  can_auto_use: true,
148
- csrf_token: includeSecrets ? csrfToken : `${csrfToken.slice(0, 8)}…`,
149
- corp_id: corpId,
150
- user_id: userId,
167
+ csrf_token: canIncludeSecrets ? csrfToken : `${csrfToken.slice(0, 8)}…`,
168
+ corp_id: outputCorpId,
169
+ user_id: outputUserId,
151
170
  base_url: baseUrl,
152
171
  cookies_count: cookies.length,
153
172
  diagnostics,
154
- message: `✅ Valid login credentials found\n Org: ${corpId}\n User: ${userId}\n Domain: ${baseUrl}`,
173
+ message: `✅ Valid login credentials found\n Org: ${outputCorpId || ''}\n User: ${outputUserId || ''}\n Domain: ${baseUrl}`,
155
174
  };
156
- if (includeSecrets) {
175
+ if (canIncludeSecrets) {
157
176
  result.cookies = cookies;
158
177
  }
159
178
  return result;
@@ -209,8 +228,8 @@ function refreshCsrfFromCache() {
209
228
  */
210
229
  function ensureLogin(options = {}) {
211
230
  const force = !!options.force;
212
- const injectedAuth = isInjectedAuthMode();
213
- if (!force || injectedAuth) {
231
+ const envAuth = isEnvAuthMode();
232
+ if (!force || envAuth) {
214
233
  const cookieData = loadCookieData();
215
234
 
216
235
  if (cookieData && cookieData.cookies) {
@@ -235,7 +254,7 @@ function ensureLogin(options = {}) {
235
254
  }
236
255
  }
237
256
 
238
- if (injectedAuth) {
257
+ if (envAuth) {
239
258
  return null;
240
259
  }
241
260
 
@@ -86,7 +86,7 @@ const COMMAND_GROUPS = [
86
86
  command('build-page', ['build-page'], 'build-page <sourceFile> [--output file|--write]', 'help.cmd_build_page', { requiresLogin: false }),
87
87
  command('check-page', ['check-page'], 'check-page <src> [--compat]', 'help.cmd_check_page', { output: 'text|json' }),
88
88
  command('compile', ['compile'], 'compile <src>', 'help.cmd_compile', { requiresLogin: false }),
89
- command('publish', ['publish'], 'publish <src> <appType> <formUuid> [--health-check] [--force] [--open|--no-open]', 'help.cmd_publish'),
89
+ command('publish', ['publish'], 'publish <src> <appType> <formUuid> [--health-check] [--force] [--canvas] [--open|--no-open]', 'help.cmd_publish'),
90
90
  command('update-form-config', ['update-form-config'], 'update-form-config <appType> ...', 'help.cmd_update_form_config'),
91
91
  ],
92
92
  },
package/lib/core/env.js CHANGED
@@ -16,6 +16,7 @@ const {
16
16
  resolveBaseUrl,
17
17
  extractInfoFromCookies,
18
18
  resolveWukongWorkspaceRoot,
19
+ getLastEnvAuthError,
19
20
  } = require('./utils');
20
21
  const { t } = require('./i18n');
21
22
 
@@ -110,6 +111,7 @@ function detectLoginStatus(projectRoot) {
110
111
  const cookieDiagnostics = getCookieDiagnostics(projectRoot);
111
112
  const cookieData = loadCookieData(projectRoot);
112
113
  const cookies = cookieData && Array.isArray(cookieData.cookies) ? cookieData.cookies : [];
114
+ const envAuthError = getLastEnvAuthError();
113
115
 
114
116
  if (!cookieData || !cookieData.cookies) {
115
117
  return {
@@ -128,7 +130,9 @@ function detectLoginStatus(projectRoot) {
128
130
  corpIdFound: false,
129
131
  userIdFound: false,
130
132
  baseUrlFound: false,
131
- failureReason: cookieDiagnostics.cookieFileFound ? 'cookie_cache_unreadable_or_invalid' : 'cookie_cache_missing',
133
+ failureReason: envAuthError
134
+ ? envAuthError.failure_reason
135
+ : (cookieDiagnostics.cookieFileFound ? 'cookie_cache_unreadable_or_invalid' : 'cookie_cache_missing'),
132
136
  },
133
137
  };
134
138
  }
@@ -139,6 +143,7 @@ function detectLoginStatus(projectRoot) {
139
143
  const userId = cookieData.user_id || cookieData.userId || cookieData.staffId || cookieInfo.userId;
140
144
  const baseUrl = resolveBaseUrl(cookieData);
141
145
  const loggedIn = !!csrfToken;
146
+ const isEnvAuth = cookieData.auth_source === 'env';
142
147
 
143
148
  return {
144
149
  loggedIn,
@@ -148,8 +153,10 @@ function detectLoginStatus(projectRoot) {
148
153
  userId,
149
154
  baseUrl,
150
155
  cookiesCount: cookies.length,
156
+ authSource: isEnvAuth ? 'env' : 'cache',
151
157
  diagnostics: {
152
158
  ...cookieDiagnostics,
159
+ authSource: isEnvAuth ? 'env' : 'cache',
153
160
  cacheReadable: true,
154
161
  cookiesArrayFound: Array.isArray(cookieData.cookies),
155
162
  csrfTokenFound: !!csrfToken,
@@ -166,6 +173,13 @@ function maskSecret(value) {
166
173
  return `${value.slice(0, 16)}...`;
167
174
  }
168
175
 
176
+ function maskIdentifier(value) {
177
+ const text = String(value || '');
178
+ if (!text) {return null;}
179
+ if (text.length <= 8) {return `${text.slice(0, 2)}***${text.slice(-1)}`;}
180
+ return `${text.slice(0, 4)}***${text.slice(-4)}`;
181
+ }
182
+
169
183
  /**
170
184
  * 构建适合 AI agent 读取的环境快照。
171
185
  */
@@ -198,9 +212,10 @@ function buildEnvironmentSnapshot() {
198
212
  loggedIn: loginStatus.loggedIn,
199
213
  canAutoUse: loginStatus.canAutoUse,
200
214
  baseUrl: loginStatus.baseUrl,
201
- corpId: loginStatus.corpId,
202
- userId: loginStatus.userId,
203
- csrfToken: maskSecret(loginStatus.csrfToken),
215
+ authSource: loginStatus.authSource || null,
216
+ corpId: loginStatus.authSource === 'env' ? maskIdentifier(loginStatus.corpId) : loginStatus.corpId,
217
+ userId: loginStatus.authSource === 'env' ? maskIdentifier(loginStatus.userId) : loginStatus.userId,
218
+ csrfToken: loginStatus.authSource === 'env' ? null : maskSecret(loginStatus.csrfToken),
204
219
  cookiesCount: loginStatus.cookiesCount,
205
220
  diagnostics: loginStatus.diagnostics,
206
221
  },
@@ -478,7 +478,7 @@ module.exports = {
478
478
  lint_array_callback_function: '.{0}(function ...) قد يفقد this داخل callbacks؛ استخدم بدلا من ذلك .{0}((item) => ...)',
479
479
  lint_foreach_callback_function: '.forEach(function ...) قد يفقد this داخل callbacks؛ يفضل استخدام .forEach((item) => ...)',
480
480
  lint_controlled_input: 'يستخدم input وضع value المتحكم به. يجب أن تستخدم صفحات Yida defaultValue + onChange لتحديث _customState',
481
- lint_native_select_ui: 'تم العثور على <select> أصلي. في صفحات الكود المخصصة يمكنك استخدام مكون Yida <SelectField> مباشرة (يتم حقنه عالميا في وقت التشغيل، ولا يحتاج import)، أو استخدام قائمة مخصصة div+button+onClick للحفاظ على تناسق التصميم وتوافق الجوال',
481
+ lint_native_select_ui: 'تم العثور على <select> أصلي. في الصفحات المخصصة العادية استخدم قائمة div+button+onClick للحفاظ على تناسق التصميم وتوافق الجوال. استخدم مكونات حقول Yida في Code Canvas فقط بعد التحقق من ربط التبعيات',
482
482
  lint_iframe_self_navigation: 'تعمل صفحات Yida المخصصة داخل iframe. استخدم target="_top"/target="_blank" أو window.top.location للتنقل إلى صفحات Yida لتجنب الصفحات المتداخلة.',
483
483
  lint_page_size_limit: 'pageSize={0} يتجاوز حد واجهة Yida API وهو 100؛ استخدم 100 أو أقل',
484
484
  lint_page_size_recommend: 'pageSize={0} كبير؛ القيمة الموصى بها هي 50 (أفضل أداء، الحد الأقصى 100). يفضل 10/20/50',
@@ -522,6 +522,10 @@ module.exports = {
522
522
  building_schema: '[4/4] جارٍ بناء المخطط...',
523
523
  formula_prefix_fixed: ' 🔧 تم تصحيح {0} من مراجع بادئة صيغة الجدول الفرعي تلقائيًا',
524
524
  schema_built: ' ✅ تم بناء المخطط بنجاح!',
525
+ step_canvas_compile: '\n📦 Step 1: تجميع مصدر Code Canvas\n',
526
+ canvas_compiling: ' 🎨 جارٍ تجميع مصدر Code Canvas محليًا...',
527
+ canvas_compile_done: ' ✅ تم تجميع Code Canvas!',
528
+ canvas_compile_failed: ' ❌ فشل تجميع Code Canvas: {0}',
525
529
  step_login: '\n🔑 Step 2: قراءة بيانات تسجيل الدخول',
526
530
  step_publish: '\n📤 Step 3: نشر المخطط\n',
527
531
  publish_failed: '\n❌ فشل النشر: {0}',
@@ -535,7 +539,7 @@ module.exports = {
535
539
  health_check_failed: ' ⚠️ Health check failed: HTTP {0} {1}',
536
540
  exception: '\n❌ خطأ في النشر: {0}',
537
541
  source_not_found: '❌ لم يتم العثور على ملف المصدر: {0}',
538
- usage: 'الاستخدام: openyida publish <ملفالمصدر> <appType> <formUuid> [--health-check]',
542
+ usage: 'الاستخدام: openyida publish <ملفالمصدر> <appType> <formUuid> [--health-check] [--canvas]',
539
543
  example: 'مثال: openyida publish pages/src/xxx.js APP_XXX FORM-XXX --health-check',
540
544
  },
541
545
 
@@ -478,7 +478,7 @@ module.exports = {
478
478
  lint_array_callback_function: '.{0}(function ...) kann this in Callbacks verlieren; verwenden Sie stattdessen .{0}((item) => ...)',
479
479
  lint_foreach_callback_function: '.forEach(function ...) kann this in Callbacks verlieren; bevorzugen Sie .forEach((item) => ...)',
480
480
  lint_controlled_input: 'input verwendet den kontrollierten value-Modus. Yida-Seiten sollten defaultValue + onChange verwenden, um _customState zu aktualisieren',
481
- lint_native_select_ui: 'Natives <select> gefunden. In Code-Benutzerdefinierten Seiten können Sie die Yida-Komponente <SelectField> direkt verwenden (zur Laufzeit global injiziert, kein Import nötig) oder auf ein benutzerdefiniertes Dropdown mit div+button+onClick zurückgreifen, für konsistentes Styling und mobile Kompatibilität',
481
+ lint_native_select_ui: 'Natives <select> gefunden. In normalen benutzerdefinierten Seiten verwenden Sie ein div+button+onClick-Dropdown für konsistentes Styling und mobile Kompatibilität. Yida-Feldkomponenten nur in Code Canvas nach Prüfung des Dependency-Mappings verwenden',
482
482
  lint_iframe_self_navigation: 'Yida-Benutzerdefinierte Seiten laufen in einer iframe. Verwenden Sie target="_top"/target="_blank" oder window.top.location für die Navigation zu Yida-Seiten, um verschachtelte Seiten zu vermeiden.',
483
483
  lint_page_size_limit: 'pageSize={0} überschreitet das Yida-API-Limit von 100; verwenden Sie 100 oder weniger',
484
484
  lint_page_size_recommend: 'pageSize={0} ist groß; der empfohlene Wert ist 50 (beste Performance, maximal 100). Bevorzugen Sie 10/20/50',
@@ -522,6 +522,10 @@ module.exports = {
522
522
  building_schema: '[4/4] Schema wird erstellt...',
523
523
  formula_prefix_fixed: ' 🔧 {0} Untertabellen-Formelpräfix-Referenz(en) automatisch korrigiert',
524
524
  schema_built: ' ✅ Schema erfolgreich erstellt!',
525
+ step_canvas_compile: '\n📦 Step 1: Code-Canvas-Quelle kompilieren\n',
526
+ canvas_compiling: ' 🎨 Code-Canvas-Quelle wird lokal kompiliert...',
527
+ canvas_compile_done: ' ✅ Code Canvas kompiliert!',
528
+ canvas_compile_failed: ' ❌ Code-Canvas-Kompilierung fehlgeschlagen: {0}',
525
529
  step_login: '\n🔑 Step 2: Anmeldedaten lesen',
526
530
  step_publish: '\n📤 Step 3: Schema veröffentlichen\n',
527
531
  publish_failed: '\n❌ Veröffentlichung fehlgeschlagen: {0}',
@@ -535,7 +539,7 @@ module.exports = {
535
539
  health_check_failed: ' ⚠️ Health check failed: HTTP {0} {1}',
536
540
  exception: '\n❌ Veröffentlichungsfehler: {0}',
537
541
  source_not_found: '❌ Quelldatei nicht gefunden: {0}',
538
- usage: 'Verwendung: openyida publish <Quelldatei> <appType> <formUuid> [--health-check]',
542
+ usage: 'Verwendung: openyida publish <Quelldatei> <appType> <formUuid> [--health-check] [--canvas]',
539
543
  example: 'Beispiel: openyida publish pages/src/xxx.js APP_XXX FORM-XXX --health-check',
540
544
  },
541
545
 
@@ -249,7 +249,7 @@ Examples:
249
249
  generate_page_example: 'Example: openyida generate-page product-homepage --brand-name OpenKuma --brand-initials OK --output pages/src/home.oyd.jsx --compile',
250
250
  build_page_usage: 'Usage: openyida build-page <sourceFile> [--output pages/build/page.yida.jsx|--write] [--json]',
251
251
  build_page_example: 'Example: openyida build-page pages/src/dashboard.oyd.jsx --output pages/build/dashboard.yida.jsx',
252
- publish_usage: 'Usage: openyida publish <sourceFile> <appType> <formUuid> [--health-check]',
252
+ publish_usage: 'Usage: openyida publish <sourceFile> <appType> <formUuid> [--health-check] [--canvas]',
253
253
  publish_example: 'Example: openyida publish pages/src/home.oyd.jsx APP_XXX FORM-XXX --health-check',
254
254
  formula_usage: 'Usage: openyida formula evaluate <formula|file> [--schema schema.json] [--json] [--strict]',
255
255
  formula_example: 'Example: openyida formula evaluate \'IF(GT(#{numberField_total}, 100), "high", "low")\' --schema .cache/schema.json',
@@ -1064,7 +1064,7 @@ Examples:
1064
1064
  lint_array_callback_function: '.{0}(function ...) may lose this in callbacks; use .{0}((item) => ...) instead',
1065
1065
  lint_foreach_callback_function: '.forEach(function ...) may lose this in callbacks; prefer .forEach((item) => ...)',
1066
1066
  lint_controlled_input: 'input uses controlled value mode. Yida pages should use defaultValue + onChange to update _customState',
1067
- lint_native_select_ui: 'Found a native <select>. In code custom pages you can use the Yida <SelectField> component directly (globally injected at runtime, no import needed), or fall back to a div+button+onClick custom dropdown, for consistent styling and mobile compatibility',
1067
+ lint_native_select_ui: 'Found a native <select>. In normal custom pages, use a div+button+onClick custom dropdown for consistent styling and mobile compatibility. Only use Yida field components in Code Canvas after verifying the dependency mapping.',
1068
1068
  lint_iframe_self_navigation: 'Yida custom pages run in an iframe. Use target="_top"/target="_blank" or window.top.location for Yida page navigation to avoid nested pages.',
1069
1069
  lint_page_size_limit: 'pageSize={0} exceeds the Yida API limit of 100; use 100 or less',
1070
1070
  lint_page_size_recommend: 'pageSize={0} is large; the recommended value is 50 (best performance, max 100). Prefer 10/20/50',
@@ -1111,6 +1111,10 @@ Examples:
1111
1111
  building_schema: '[4/4] Building Schema...',
1112
1112
  formula_prefix_fixed: ' 🔧 Auto-fixed {0} subtable formula prefix reference(s)',
1113
1113
  schema_built: ' ✅ Schema built successfully!',
1114
+ step_canvas_compile: '\n📦 Step 1: Compile Code Canvas source\n',
1115
+ canvas_compiling: ' 🎨 Compiling Code Canvas source locally...',
1116
+ canvas_compile_done: ' ✅ Code Canvas compiled!',
1117
+ canvas_compile_failed: ' ❌ Code Canvas compile failed: {0}',
1114
1118
  step_login: '\n🔑 Step 2: Read login credentials',
1115
1119
  step_publish: '\n📤 Step 3: Publish Schema\n',
1116
1120
  resend_save_csrf: ' 🔄 Resending saveFormSchema request (csrf_token refreshed)...',
@@ -1140,7 +1144,7 @@ Examples:
1140
1144
  exception: '\n❌ Publish error: {0}',
1141
1145
  error: '\n❌ Publish error: {0}',
1142
1146
  source_not_found: '❌ Source file not found: {0}',
1143
- usage: 'Usage: openyida publish <sourceFile> <appType> <formUuid> [--health-check]',
1147
+ usage: 'Usage: openyida publish <sourceFile> <appType> <formUuid> [--health-check] [--canvas]',
1144
1148
  example: 'Example: openyida publish pages/src/xxx.js APP_XXX FORM-XXX --health-check',
1145
1149
  },
1146
1150
 
@@ -478,7 +478,7 @@ module.exports = {
478
478
  lint_array_callback_function: '.{0}(function ...) puede perder this en callbacks; use .{0}((item) => ...) en su lugar',
479
479
  lint_foreach_callback_function: '.forEach(function ...) puede perder this en callbacks; prefiera .forEach((item) => ...)',
480
480
  lint_controlled_input: 'input usa el modo controlado con value. Las páginas de Yida deben usar defaultValue + onChange para actualizar _customState',
481
- lint_native_select_ui: 'Se encontró un <select> nativo. En páginas personalizadas de código puede usar directamente el componente Yida <SelectField> (inyectado globalmente en runtime, sin import), o usar un desplegable personalizado div+button+onClick para mantener estilo consistente y compatibilidad móvil',
481
+ lint_native_select_ui: 'Se encontró un <select> nativo. En páginas personalizadas normales use un desplegable div+button+onClick para mantener estilo consistente y compatibilidad móvil. Use componentes de campo Yida en Code Canvas solo tras verificar el mapeo de dependencias',
482
482
  lint_iframe_self_navigation: 'Las páginas personalizadas de Yida se ejecutan en un iframe. Use target="_top"/target="_blank" o window.top.location para navegar a páginas de Yida y evitar páginas anidadas.',
483
483
  lint_page_size_limit: 'pageSize={0} supera el límite de la API de Yida de 100; use 100 o menos',
484
484
  lint_page_size_recommend: 'pageSize={0} es grande; el valor recomendado es 50 (mejor rendimiento, máximo 100). Prefiera 10/20/50',
@@ -522,6 +522,10 @@ module.exports = {
522
522
  building_schema: '[4/4] Construyendo esquema...',
523
523
  formula_prefix_fixed: ' 🔧 {0} referencia(s) de prefijo de fórmula de subtabla corregida(s) automáticamente',
524
524
  schema_built: ' ✅ ¡Esquema construido exitosamente!',
525
+ step_canvas_compile: '\n📦 Step 1: Compilar fuente de Code Canvas\n',
526
+ canvas_compiling: ' 🎨 Compilando la fuente de Code Canvas localmente...',
527
+ canvas_compile_done: ' ✅ ¡Code Canvas compilado!',
528
+ canvas_compile_failed: ' ❌ Error al compilar Code Canvas: {0}',
525
529
  step_login: '\n🔑 Step 2: Leer credenciales de sesión',
526
530
  step_publish: '\n📤 Step 3: Publicar esquema\n',
527
531
  publish_failed: '\n❌ Error al publicar: {0}',
@@ -535,7 +539,7 @@ module.exports = {
535
539
  health_check_failed: ' ⚠️ Health check failed: HTTP {0} {1}',
536
540
  exception: '\n❌ Error de publicación: {0}',
537
541
  source_not_found: '❌ Archivo fuente no encontrado: {0}',
538
- usage: 'Uso: openyida publish <archivoFuente> <appType> <formUuid> [--health-check]',
542
+ usage: 'Uso: openyida publish <archivoFuente> <appType> <formUuid> [--health-check] [--canvas]',
539
543
  example: 'Ejemplo: openyida publish pages/src/xxx.js APP_XXX FORM-XXX --health-check',
540
544
  },
541
545
 
@@ -478,7 +478,7 @@ module.exports = {
478
478
  lint_array_callback_function: '.{0}(function ...) peut perdre this dans les callbacks ; utilisez plutôt .{0}((item) => ...)',
479
479
  lint_foreach_callback_function: '.forEach(function ...) peut perdre this dans les callbacks ; préférez .forEach((item) => ...)',
480
480
  lint_controlled_input: 'input utilise le mode contrôlé par value. Les pages Yida doivent utiliser defaultValue + onChange pour mettre à jour _customState',
481
- lint_native_select_ui: 'Un <select> natif a été détecté. Dans les pages personnalisées de code, vous pouvez utiliser directement le composant Yida <SelectField> (injecté globalement à l\'exécution, sans import), ou un menu personnalisé div+button+onClick pour un style cohérent et une compatibilité mobile',
481
+ lint_native_select_ui: 'Un <select> natif a été détecté. Dans les pages personnalisées classiques, utilisez un menu div+button+onClick pour un style cohérent et une compatibilité mobile. Utilisez les composants de champ Yida dans Code Canvas uniquement après avoir vérifié le mapping des dépendances',
482
482
  lint_iframe_self_navigation: 'Les pages personnalisées Yida s\'exécutent dans une iframe. Utilisez target="_top"/target="_blank" ou window.top.location pour naviguer vers une page Yida afin d\'éviter les pages imbriquées.',
483
483
  lint_page_size_limit: 'pageSize={0} dépasse la limite de l\'API Yida de 100 ; utilisez 100 ou moins',
484
484
  lint_page_size_recommend: 'pageSize={0} est élevé ; la valeur recommandée est 50 (meilleures performances, maximum 100). Préférez 10/20/50',
@@ -522,6 +522,10 @@ module.exports = {
522
522
  building_schema: '[4/4] Construction du schéma...',
523
523
  formula_prefix_fixed: ' 🔧 {0} référence(s) de préfixe de formule de sous-table corrigée(s) automatiquement',
524
524
  schema_built: ' ✅ Schéma construit avec succès !',
525
+ step_canvas_compile: '\n📦 Step 1 : Compilation de la source Code Canvas\n',
526
+ canvas_compiling: ' 🎨 Compilation locale de la source Code Canvas...',
527
+ canvas_compile_done: ' ✅ Code Canvas compilé !',
528
+ canvas_compile_failed: ' ❌ Échec de la compilation Code Canvas : {0}',
525
529
  step_login: '\n🔑 Step 2 : Lecture des identifiants',
526
530
  step_publish: '\n📤 Step 3 : Publication du schéma\n',
527
531
  publish_failed: '\n❌ Échec de la publication : {0}',
@@ -535,7 +539,7 @@ module.exports = {
535
539
  health_check_failed: ' ⚠️ Health check failed: HTTP {0} {1}',
536
540
  exception: '\n❌ Erreur de publication : {0}',
537
541
  source_not_found: '❌ Fichier source introuvable : {0}',
538
- usage: 'Utilisation : openyida publish <fichierSource> <appType> <formUuid> [--health-check]',
542
+ usage: 'Utilisation : openyida publish <fichierSource> <appType> <formUuid> [--health-check] [--canvas]',
539
543
  example: 'Exemple : openyida publish pages/src/xxx.js APP_XXX FORM-XXX --health-check',
540
544
  },
541
545
 
@@ -478,7 +478,7 @@ module.exports = {
478
478
  lint_array_callback_function: '.{0}(function ...) callbacks में this खो सकता है; इसके बजाय .{0}((item) => ...) उपयोग करें',
479
479
  lint_foreach_callback_function: '.forEach(function ...) callbacks में this खो सकता है; .forEach((item) => ...) बेहतर है',
480
480
  lint_controlled_input: 'input controlled value mode का उपयोग करता है। Yida पेजों को _customState update करने के लिए defaultValue + onChange उपयोग करना चाहिए',
481
- lint_native_select_ui: 'Native <select> मिला। Code custom pages में आप Yida <SelectField> component सीधे उपयोग कर सकते हैं (runtime पर वैश्विक रूप से inject होता है, import की जरूरत नहीं), या consistent styling और mobile compatibility के लिए div+button+onClick custom dropdown उपयोग करें',
481
+ lint_native_select_ui: 'Native <select> मिला। Normal custom pages में consistent styling और mobile compatibility के लिए div+button+onClick custom dropdown उपयोग करें। Yida field components को Code Canvas में dependency mapping verify करने के बाद ही उपयोग करें',
482
482
  lint_iframe_self_navigation: 'Yida custom pages iframe में चलते हैं। Nested pages से बचने के लिए Yida page navigation में target="_top"/target="_blank" या window.top.location उपयोग करें।',
483
483
  lint_page_size_limit: 'pageSize={0} Yida API की 100 सीमा से अधिक है; 100 या उससे कम उपयोग करें',
484
484
  lint_page_size_recommend: 'pageSize={0} बड़ा है; अनुशंसित मान 50 है (best performance, max 100)। 10/20/50 को प्राथमिकता दें',
@@ -522,6 +522,10 @@ module.exports = {
522
522
  building_schema: '[4/4] स्कीमा बनाया जा रहा है...',
523
523
  formula_prefix_fixed: ' 🔧 {0} सबटेबल फ़ॉर्मूला उपसर्ग संदर्भ स्वतः ठीक किए गए',
524
524
  schema_built: ' ✅ स्कीमा सफलतापूर्वक बना!',
525
+ step_canvas_compile: '\n📦 Step 1: Code Canvas स्रोत संकलित करें\n',
526
+ canvas_compiling: ' 🎨 Code Canvas स्रोत को स्थानीय रूप से संकलित किया जा रहा है...',
527
+ canvas_compile_done: ' ✅ Code Canvas संकलित!',
528
+ canvas_compile_failed: ' ❌ Code Canvas संकलन विफल: {0}',
525
529
  step_login: '\n🔑 Step 2: लॉगिन जानकारी पढ़ें',
526
530
  step_publish: '\n📤 Step 3: स्कीमा प्रकाशित करें\n',
527
531
  publish_failed: '\n❌ प्रकाशन विफल: {0}',
@@ -535,7 +539,7 @@ module.exports = {
535
539
  health_check_failed: ' ⚠️ Health check failed: HTTP {0} {1}',
536
540
  exception: '\n❌ प्रकाशन त्रुटि: {0}',
537
541
  source_not_found: '❌ स्रोत फ़ाइल नहीं मिली: {0}',
538
- usage: 'उपयोग: openyida publish <स्रोतफ़ाइल> <appType> <formUuid> [--health-check]',
542
+ usage: 'उपयोग: openyida publish <स्रोतफ़ाइल> <appType> <formUuid> [--health-check] [--canvas]',
539
543
  example: 'उदाहरण: openyida publish pages/src/xxx.js APP_XXX FORM-XXX --health-check',
540
544
  },
541
545
 
@@ -230,7 +230,7 @@ openyida - Yida CLI ツール
230
230
  check_page_example: 'Example: openyida check-page pages/src/home.oyd.jsx --json',
231
231
  generate_page_usage: 'Usage: openyida generate-page <template> --output pages/src/home.oyd.jsx [--spec .cache/openyida/page-specs/home.json] [--compile]',
232
232
  generate_page_example: 'Example: openyida generate-page product-homepage --brand-name OpenKuma --brand-initials OK --output pages/src/home.oyd.jsx --compile',
233
- publish_usage: '使用方法: openyida publish <ソースファイル> <appType> <formUuid> [--health-check]',
233
+ publish_usage: '使用方法: openyida publish <ソースファイル> <appType> <formUuid> [--health-check] [--canvas]',
234
234
  publish_example: '例: openyida publish pages/src/home.oyd.jsx APP_XXX FORM-XXX --health-check',
235
235
  verify_usage: '使用方法: openyida verify-short-url <appType> <formUuid> <url>',
236
236
  verify_example: '例: openyida verify-short-url APP_XXX FORM-XXX /o/myapp',
@@ -899,7 +899,7 @@ openyida - Yida CLI ツール
899
899
  lint_array_callback_function: '.{0}(function ...) はコールバック内で this を失う可能性があります。代わりに .{0}((item) => ...) を使用してください',
900
900
  lint_foreach_callback_function: '.forEach(function ...) はコールバック内で this を失う可能性があります。.forEach((item) => ...) を推奨します',
901
901
  lint_controlled_input: 'input が value による controlled モードを使用しています。Yida ページでは defaultValue + onChange で _customState を更新してください',
902
- lint_native_select_ui: 'ネイティブの <select> が見つかりました。コードカスタムページでは Yida の <SelectField> コンポーネントを直接使用できます(ランタイムでグローバル注入、import 不要)。または、一貫したスタイルとモバイル互換性のため div+button+onClick のカスタムドロップダウンを使用してください',
902
+ lint_native_select_ui: 'ネイティブの <select> が見つかりました。通常のカスタムページでは div+button+onClick のカスタムドロップダウンを使用してください。Yida フィールドコンポーネントは、Code Canvas で依存関係マッピングを確認した場合のみ使用してください',
903
903
  lint_iframe_self_navigation: 'Yida カスタムページは iframe 内で実行されます。Yida ページへ遷移する場合は、ネストしたページを避けるため target="_top"/target="_blank" または window.top.location を使用してください。',
904
904
  lint_page_size_limit: 'pageSize={0} は Yida API の上限 100 を超えています。100 以下を使用してください',
905
905
  lint_page_size_recommend: 'pageSize={0} は大きすぎます。推奨値は 50(最高のパフォーマンス、最大 100)です。10/20/50 を優先してください',
@@ -946,6 +946,10 @@ openyida - Yida CLI ツール
946
946
  building_schema: '[4/4] Schema を構築中...',
947
947
  formula_prefix_fixed: ' 🔧 サブテーブル数式の接頭辞参照を {0} 件自動修正しました',
948
948
  schema_built: ' ✅ Schema の構築が完了しました!',
949
+ step_canvas_compile: '\n📦 Step 1: Code Canvas ソースをコンパイル\n',
950
+ canvas_compiling: ' 🎨 Code Canvas ソースをローカルでコンパイル中...',
951
+ canvas_compile_done: ' ✅ Code Canvas のコンパイルが完了しました!',
952
+ canvas_compile_failed: ' ❌ Code Canvas のコンパイルに失敗しました:{0}',
949
953
  step_login: '\n🔑 Step 2: ログイン情報を読み込む',
950
954
  step_publish: '\n📤 Step 3: Schema を公開\n',
951
955
  resend_save_csrf: ' 🔄 saveFormSchema リクエストを再送信中(csrf_token を更新済み)...',
@@ -975,7 +979,7 @@ openyida - Yida CLI ツール
975
979
  exception: '\n❌ 公開エラー: {0}',
976
980
  error: '\n❌ 公開エラー: {0}',
977
981
  source_not_found: '❌ ソースファイルが見つかりません:{0}',
978
- usage: '使用方法: openyida publish <ソースファイル> <appType> <formUuid> [--health-check]',
982
+ usage: '使用方法: openyida publish <ソースファイル> <appType> <formUuid> [--health-check] [--canvas]',
979
983
  example: '例: openyida publish pages/src/xxx.js APP_XXX FORM-XXX --health-check',
980
984
  },
981
985
 
@@ -480,7 +480,7 @@ module.exports = {
480
480
  lint_array_callback_function: '.{0}(function ...)은 콜백에서 this를 잃을 수 있습니다. 대신 .{0}((item) => ...)를 사용하세요',
481
481
  lint_foreach_callback_function: '.forEach(function ...)은 콜백에서 this를 잃을 수 있습니다. .forEach((item) => ...)를 권장합니다',
482
482
  lint_controlled_input: 'input이 value 제어 모드를 사용합니다. Yida 페이지는 defaultValue + onChange로 _customState를 업데이트해야 합니다',
483
- lint_native_select_ui: '네이티브 <select>가 발견되었습니다. 코드 사용자 정의 페이지에서는 Yida <SelectField> 컴포넌트를 직접 사용할 수 있습니다(런타임에 전역 주입, import 불필요). 또는 일관된 스타일과 모바일 호환성을 위해 div+button+onClick 사용자 정의 드롭다운을 사용하세요',
483
+ lint_native_select_ui: '네이티브 <select>가 발견되었습니다. 일반 사용자 정의 페이지에서는 스타일과 모바일 호환성을 위해 div+button+onClick 사용자 정의 드롭다운을 사용하세요. Yida 필드 컴포넌트는 Code Canvas에서 의존성 매핑을 확인한 뒤에만 사용하세요',
484
484
  lint_iframe_self_navigation: 'Yida 사용자 정의 페이지는 iframe 안에서 실행됩니다. 중첩 페이지를 피하려면 Yida 페이지 이동에 target="_top"/target="_blank" 또는 window.top.location을 사용하세요.',
485
485
  lint_page_size_limit: 'pageSize={0}이 Yida API 제한 100을 초과합니다. 100 이하를 사용하세요',
486
486
  lint_page_size_recommend: 'pageSize={0}이 큽니다. 권장값은 50입니다(최고 성능, 최대 100). 10/20/50을 우선 사용하세요',
@@ -524,6 +524,10 @@ module.exports = {
524
524
  building_schema: '[4/4] 스키마 빌드 중...',
525
525
  formula_prefix_fixed: ' 🔧 하위 테이블 수식 접두사 참조 {0}개를 자동 수정했습니다',
526
526
  schema_built: ' ✅ 스키마 빌드 완료!',
527
+ step_canvas_compile: '\n📦 Step 1: Code Canvas 소스 컴파일\n',
528
+ canvas_compiling: ' 🎨 Code Canvas 소스를 로컬에서 컴파일하는 중...',
529
+ canvas_compile_done: ' ✅ Code Canvas 컴파일 완료!',
530
+ canvas_compile_failed: ' ❌ Code Canvas 컴파일 실패: {0}',
527
531
  step_login: '\n🔑 Step 2: 로그인 정보 읽기',
528
532
  step_publish: '\n📤 Step 3: 스키마 배포\n',
529
533
  publish_failed: '\n❌ 배포 실패: {0}',
@@ -537,7 +541,7 @@ module.exports = {
537
541
  health_check_failed: ' ⚠️ Health check failed: HTTP {0} {1}',
538
542
  exception: '\n❌ 배포 오류: {0}',
539
543
  source_not_found: '❌ 소스 파일을 찾을 수 없습니다: {0}',
540
- usage: '사용법: openyida publish <소스 파일> <appType> <formUuid> [--health-check]',
544
+ usage: '사용법: openyida publish <소스 파일> <appType> <formUuid> [--health-check] [--canvas]',
541
545
  example: '예시: openyida publish pages/src/xxx.js APP_XXX FORM-XXX --health-check',
542
546
  },
543
547
 
@@ -478,7 +478,7 @@ module.exports = {
478
478
  lint_array_callback_function: '.{0}(function ...) pode perder this em callbacks; use .{0}((item) => ...) em vez disso',
479
479
  lint_foreach_callback_function: '.forEach(function ...) pode perder this em callbacks; prefira .forEach((item) => ...)',
480
480
  lint_controlled_input: 'input usa modo controlado por value. Páginas do Yida devem usar defaultValue + onChange para atualizar _customState',
481
- lint_native_select_ui: 'Foi encontrado um <select> nativo. Em páginas personalizadas de código, você pode usar diretamente o componente Yida <SelectField> (injetado globalmente no runtime, sem import), ou usar um dropdown personalizado com div+button+onClick para manter estilo consistente e compatibilidade móvel',
481
+ lint_native_select_ui: 'Foi encontrado um <select> nativo. Em páginas personalizadas normais, use um dropdown div+button+onClick para manter estilo consistente e compatibilidade móvel. Use componentes de campo Yida no Code Canvas somente após verificar o mapeamento de dependências',
482
482
  lint_iframe_self_navigation: 'Páginas personalizadas do Yida rodam em um iframe. Use target="_top"/target="_blank" ou window.top.location para navegar para páginas do Yida e evitar páginas aninhadas.',
483
483
  lint_page_size_limit: 'pageSize={0} excede o limite da API do Yida de 100; use 100 ou menos',
484
484
  lint_page_size_recommend: 'pageSize={0} é grande; o valor recomendado é 50 (melhor desempenho, máximo 100). Prefira 10/20/50',
@@ -522,6 +522,10 @@ module.exports = {
522
522
  building_schema: '[4/4] Construindo esquema...',
523
523
  formula_prefix_fixed: ' 🔧 {0} referência(s) de prefixo de fórmula de subtabela corrigida(s) automaticamente',
524
524
  schema_built: ' ✅ Esquema construído com sucesso!',
525
+ step_canvas_compile: '\n📦 Step 1: Compilar fonte do Code Canvas\n',
526
+ canvas_compiling: ' 🎨 Compilando a origem do Code Canvas localmente...',
527
+ canvas_compile_done: ' ✅ Code Canvas compilado!',
528
+ canvas_compile_failed: ' ❌ Falha na compilação do Code Canvas: {0}',
525
529
  step_login: '\n🔑 Step 2: Ler credenciais de login',
526
530
  step_publish: '\n📤 Step 3: Publicar esquema\n',
527
531
  publish_failed: '\n❌ Falha na publicação: {0}',
@@ -535,7 +539,7 @@ module.exports = {
535
539
  health_check_failed: ' ⚠️ Health check failed: HTTP {0} {1}',
536
540
  exception: '\n❌ Erro de publicação: {0}',
537
541
  source_not_found: '❌ Arquivo fonte não encontrado: {0}',
538
- usage: 'Uso: openyida publish <arquivoFonte> <appType> <formUuid> [--health-check]',
542
+ usage: 'Uso: openyida publish <arquivoFonte> <appType> <formUuid> [--health-check] [--canvas]',
539
543
  example: 'Exemplo: openyida publish pages/src/xxx.js APP_XXX FORM-XXX --health-check',
540
544
  },
541
545
 
@@ -478,7 +478,7 @@ module.exports = {
478
478
  lint_array_callback_function: '.{0}(function ...) có thể mất this trong callback; hãy dùng .{0}((item) => ...) thay thế',
479
479
  lint_foreach_callback_function: '.forEach(function ...) có thể mất this trong callback; nên dùng .forEach((item) => ...)',
480
480
  lint_controlled_input: 'input dùng chế độ controlled value. Trang Yida nên dùng defaultValue + onChange để cập nhật _customState',
481
- lint_native_select_ui: 'Phát hiện <select> native. Trong trang tùy chỉnh bằng code, bạn có thể dùng trực tiếp component Yida <SelectField> (được inject global lúc runtime, không cần import), hoặc dùng dropdown tùy chỉnh div+button+onClick để giữ style nhất quán tương thích mobile',
481
+ lint_native_select_ui: 'Phát hiện <select> native. Với trang tùy chỉnh thông thường, dùng dropdown div+button+onClick để giữ style nhất quán tương thích mobile. Chỉ dùng component trường Yida trong Code Canvas sau khi xác minh mapping dependency',
482
482
  lint_iframe_self_navigation: 'Trang tùy chỉnh Yida chạy trong iframe. Dùng target="_top"/target="_blank" hoặc window.top.location khi điều hướng trang Yida để tránh trang lồng nhau.',
483
483
  lint_page_size_limit: 'pageSize={0} vượt quá giới hạn API Yida là 100; hãy dùng 100 hoặc nhỏ hơn',
484
484
  lint_page_size_recommend: 'pageSize={0} lớn; giá trị khuyến nghị là 50 (hiệu năng tốt nhất, tối đa 100). Ưu tiên 10/20/50',
@@ -522,6 +522,10 @@ module.exports = {
522
522
  building_schema: '[4/4] Đang xây dựng schema...',
523
523
  formula_prefix_fixed: ' 🔧 Đã tự động sửa {0} tham chiếu tiền tố công thức bảng con',
524
524
  schema_built: ' ✅ Xây dựng schema thành công!',
525
+ step_canvas_compile: '\n📦 Step 1: Biên dịch mã nguồn Code Canvas\n',
526
+ canvas_compiling: ' 🎨 Đang biên dịch mã nguồn Code Canvas cục bộ...',
527
+ canvas_compile_done: ' ✅ Đã biên dịch Code Canvas!',
528
+ canvas_compile_failed: ' ❌ Biên dịch Code Canvas thất bại: {0}',
525
529
  step_login: '\n🔑 Step 2: Đọc thông tin đăng nhập',
526
530
  step_publish: '\n📤 Step 3: Xuất bản schema\n',
527
531
  publish_failed: '\n❌ Xuất bản thất bại: {0}',
@@ -535,7 +539,7 @@ module.exports = {
535
539
  health_check_failed: ' ⚠️ Health check failed: HTTP {0} {1}',
536
540
  exception: '\n❌ Lỗi xuất bản: {0}',
537
541
  source_not_found: '❌ Không tìm thấy tệp nguồn: {0}',
538
- usage: 'Cách dùng: openyida publish <tệpNguồn> <appType> <formUuid> [--health-check]',
542
+ usage: 'Cách dùng: openyida publish <tệpNguồn> <appType> <formUuid> [--health-check] [--canvas]',
539
543
  example: 'Ví dụ: openyida publish pages/src/xxx.js APP_XXX FORM-XXX --health-check',
540
544
  },
541
545
 
@@ -229,7 +229,7 @@ openyida - 宜搭命令列工具
229
229
  check_page_example: '範例:openyida check-page pages/src/home.oyd.jsx --json',
230
230
  generate_page_usage: '用法:openyida generate-page <template> --output pages/src/home.oyd.jsx [--spec .cache/openyida/page-specs/home.json] [--compile]',
231
231
  generate_page_example: '範例:openyida generate-page product-homepage --brand-name OpenKuma --brand-initials OK --output pages/src/home.oyd.jsx --compile',
232
- publish_usage: '用法:openyida publish <原始檔路徑> <appType> <formUuid> [--health-check]',
232
+ publish_usage: '用法:openyida publish <原始檔路徑> <appType> <formUuid> [--health-check] [--canvas]',
233
233
  publish_example: '範例:openyida publish pages/src/home.oyd.jsx APP_XXX FORM-XXX --health-check',
234
234
  verify_usage: '用法:openyida verify-short-url <appType> <formUuid> <url>',
235
235
  verify_example: '範例:openyida verify-short-url APP_XXX FORM-XXX /o/myapp',
@@ -810,7 +810,7 @@ openyida - 宜搭命令列工具
810
810
  lint_array_callback_function: '.{0}(function ...) 會導致回調內 this 遺失,請改為 .{0}((item) => ...)',
811
811
  lint_foreach_callback_function: '.forEach(function ...) 可能導致回調內 this 遺失,建議改為 .forEach((item) => ...)',
812
812
  lint_controlled_input: 'input 使用了 value 受控模式,宜搭頁面應使用 defaultValue + onChange 寫入 _customState',
813
- lint_native_select_ui: '偵測到原生 <select>,樣式不一致且行動端相容性差。請改用宜搭內建的 SelectField 組件(this.$(fieldId) 或 <SelectField>),或用 div+button+onClick 實作自訂下拉',
813
+ lint_native_select_ui: '偵測到原生 <select>,樣式不一致且行動端相容性差。一般自訂頁請用 div+button+onClick 實作自訂下拉;只有 Code Canvas 場景在確認依賴映射可用後,才使用宜搭欄位組件。',
814
814
  lint_iframe_self_navigation: '宜搭自訂頁面運行在 iframe 中,跳轉宜搭頁面時請使用 target="_top"/target="_blank" 或 window.top.location,避免頁面套娃',
815
815
  lint_page_size_limit: 'pageSize={0} 超過宜搭 API 上限 100,請改為 100 或更小',
816
816
  lint_page_size_recommend: 'pageSize={0} 偏大,推薦使用 50(效能最佳,最大 100),優先選擇 10/20/50',
@@ -857,6 +857,10 @@ openyida - 宜搭命令列工具
857
857
  building_schema: '[4/4] 建構 Schema...',
858
858
  formula_prefix_fixed: ' 🔧 已自動修正 {0} 處子表公式前綴引用',
859
859
  schema_built: ' ✅ Schema 建構完成!',
860
+ step_canvas_compile: '\n📦 Step 1: 編譯 Code Canvas 原始碼\n',
861
+ canvas_compiling: ' 🎨 本機編譯 Code Canvas 源碼...',
862
+ canvas_compile_done: ' ✅ Code Canvas 編譯完成!',
863
+ canvas_compile_failed: ' ❌ Code Canvas 編譯失敗:{0}',
860
864
  step_login: '\n🔑 Step 2:讀取登入態',
861
865
  step_publish: '\n📤 Step 3:發布 Schema\n',
862
866
  resend_save_csrf: ' 🔄 重新傳送 saveFormSchema 請求(csrf_token 已刷新)...',
@@ -886,7 +890,7 @@ openyida - 宜搭命令列工具
886
890
  exception: '\n❌ 發布異常:{0}',
887
891
  error: '\n❌ 發布異常:{0}',
888
892
  source_not_found: '❌ 原始檔案不存在:{0}',
889
- usage: '用法:openyida publish <原始檔路徑> <appType> <formUuid> [--health-check]',
893
+ usage: '用法:openyida publish <原始檔路徑> <appType> <formUuid> [--health-check] [--canvas]',
890
894
  example: '範例:openyida publish pages/src/xxx.js APP_XXX FORM-XXX --health-check',
891
895
  },
892
896