kingkont 0.7.89 → 0.7.90

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 (2) hide show
  1. package/package.json +1 -1
  2. package/renderer/state.js +31 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kingkont",
3
- "version": "0.7.89",
3
+ "version": "0.7.90",
4
4
  "description": "KingKont · Chatium — нод-редактор сцен с AI-генерацией (картинки/видео/голос/SFX/музыка/текст)",
5
5
  "main": "main.js",
6
6
  "bin": {
package/renderer/state.js CHANGED
@@ -86,7 +86,38 @@ async function fileExists(handle, name) {
86
86
  try { await handle.getFileHandle(name); return true; } catch { return false; }
87
87
  }
88
88
 
89
+ // Имена из внешних источников (drag-drop из Telegram/чатов, paste, импорт)
90
+ // часто содержат символы, недопустимые для File-System-Access-API: двоеточия
91
+ // (timestamp'ы вроде «IMAGE 16:48:03.jpg»), слэши, *, ? и control-символы.
92
+ // FS-Access-API строго следует правилам Windows-FS, поэтому даже на macOS
93
+ // getFileHandle('foo:bar.jpg') бросает 'Name is not allowed'.
94
+ function sanitizeFilename(name) {
95
+ if (!name) return 'file';
96
+ let safe = String(name)
97
+ .replace(/[\\/:*?"<>|\x00-\x1F]/g, '-') // зарезервированные + control-chars
98
+ .replace(/^\.+/, '') // имя не должно начинаться с точки
99
+ .replace(/[. ]+$/, '') // и не должно кончаться на точку/пробел (Windows)
100
+ .trim();
101
+ if (!safe) safe = 'file';
102
+ // Зарезервированные базовые имена Windows.
103
+ const reserved = /^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\..*)?$/i;
104
+ if (reserved.test(safe)) safe = '_' + safe;
105
+ // Лимит длины (NTFS = 255, оставляем запас под суффикс _N).
106
+ if (safe.length > 200) {
107
+ const dot = safe.lastIndexOf('.');
108
+ if (dot > 0 && safe.length - dot < 20) {
109
+ safe = safe.slice(0, 200 - (safe.length - dot)) + safe.slice(dot);
110
+ } else {
111
+ safe = safe.slice(0, 200);
112
+ }
113
+ }
114
+ return safe;
115
+ }
116
+
89
117
  async function uniqueName(handle, name) {
118
+ // Always sanitize — uniqueName это «бутылочное горлышко» для всех импортов
119
+ // и записей с внешними именами. Если уже sanitized — операция идемпотентна.
120
+ name = sanitizeFilename(name);
90
121
  if (!(await fileExists(handle, name))) return name;
91
122
  const dot = name.lastIndexOf('.');
92
123
  const base = dot > 0 ? name.slice(0, dot) : name;