adofai 2.9.7

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.
@@ -0,0 +1,501 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>ADOFAI编辑器</title>
8
+ <!-- 引入Tailwind CSS -->
9
+ <script src="https://cdn.tailwindcss.com"></script>
10
+ <!-- 引入Font Awesome -->
11
+ <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
12
+ <!-- 引入Vue 3 -->
13
+ <script src="https://cdn.jsdelivr.net/npm/vue@3.3.4/dist/vue.global.prod.js"></script>
14
+ <!-- 引入Ace Editor -->
15
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.10.0/ace.min.js"></script>
16
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.10.0/mode-json.min.js"></script>
17
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.10.0/theme-monokai.min.js"></script>
18
+ <script src="../dist/adofai.min.js"></script>
19
+
20
+ <!-- 配置Tailwind -->
21
+ <script>
22
+ tailwind.config = {
23
+ theme: {
24
+ extend: {
25
+ colors: {
26
+ primary: '#4F46E5', // 主色调:靛蓝色
27
+ secondary: '#EC4899', // 辅助色:粉色
28
+ accent: '#3B82F6', // 强调色:蓝色
29
+ dark: '#1E293B', // 深色背景
30
+ light: '#F8FAFC', // 浅色背景
31
+ },
32
+ fontFamily: {
33
+ inter: ['Inter', 'system-ui', 'sans-serif'],
34
+ },
35
+ },
36
+ }
37
+ }
38
+ </script>
39
+
40
+ <!-- 自定义工具类 -->
41
+ <style type="text/tailwindcss">
42
+ @layer utilities {
43
+ .content-auto {
44
+ content-visibility: auto;
45
+ }
46
+ .card-shadow {
47
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
48
+ }
49
+ .transition-custom {
50
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
51
+ }
52
+ .gradient-bg {
53
+ background: linear-gradient(135deg, #4F46E5 0%, #8B5CF6 100%);
54
+ }
55
+ }
56
+ </style>
57
+ </head>
58
+
59
+ <body class="font-inter bg-gray-50 text-gray-800 min-h-screen flex flex-col">
60
+ <!-- 导航栏 -->
61
+ <header class="gradient-bg text-white shadow-lg">
62
+ <div class="container mx-auto px-4 py-4 flex justify-between items-center">
63
+ <div class="flex items-center space-x-3">
64
+ <i class="fa fa-cube text-2xl"></i>
65
+ <h1 class="text-xl md:text-2xl font-bold">ADOFAI 编辑器</h1>
66
+ </div>
67
+ <div class="flex items-center space-x-4">
68
+ <button id="exportBtn"
69
+ class="bg-white text-primary px-4 py-2 rounded-lg font-medium shadow-md hover:shadow-lg transition-custom flex items-center">
70
+ <i class="fa fa-download mr-2"></i> 导出文件
71
+ </button>
72
+ </div>
73
+ </div>
74
+ </header>
75
+
76
+ <!-- 主内容区 -->
77
+ <main class="flex-grow container mx-auto px-4 py-6">
78
+ <!-- 文件上传区 -->
79
+ <section class="mb-8">
80
+ <div class="bg-white rounded-xl p-6 card-shadow">
81
+ <h2 class="text-xl font-bold mb-4 flex items-center text-primary">
82
+ <i class="fa fa-upload mr-2"></i> 文件上传
83
+ </h2>
84
+ <div class="flex flex-col md:flex-row items-center space-y-4 md:space-y-0 md:space-x-4">
85
+ <label for="inputFile"
86
+ class="flex-1 border-2 border-dashed border-gray-300 rounded-lg p-4 text-center cursor-pointer hover:border-primary transition-custom">
87
+ <div class="flex flex-col items-center">
88
+ <i class="fa fa-file-text-o text-4xl text-gray-400 mb-2"></i>
89
+ <span class="text-gray-600">点击或拖拽文件到此处上传</span>
90
+ <span class="text-xs text-gray-500 mt-1">支持 .adofai 格式</span>
91
+ </div>
92
+ <input type="file" id="inputFile" class="hidden" accept=".adofai">
93
+ </label>
94
+ <div id="fileInfo" class="hidden bg-gray-100 rounded-lg p-4 flex-1">
95
+ <div class="flex items-center justify-between">
96
+ <div>
97
+ <h3 class="font-medium text-primary" id="fileName">未选择文件</h3>
98
+ <p class="text-sm text-gray-500" id="fileSize">0 KB</p>
99
+ </div>
100
+ <button id="resetFile" class="text-gray-400 hover:text-red-500 transition-custom">
101
+ <i class="fa fa-times-circle"></i>
102
+ </button>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ </section>
108
+
109
+ <!-- 操作控制区 -->
110
+ <section class="mb-8">
111
+ <div class="bg-white rounded-xl p-6 card-shadow">
112
+ <h2 class="text-xl font-bold mb-6 flex items-center text-primary">
113
+ <i class="fa fa-sliders mr-2"></i> 砖块操作
114
+ </h2>
115
+
116
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
117
+ <!-- 插入砖块 -->
118
+ <div class="bg-gray-50 rounded-lg p-5 border-l-4 border-primary transition-custom hover:shadow-md">
119
+ <h3 class="font-semibold text-lg mb-4 flex items-center">
120
+ <i class="fa fa-plus-circle text-primary mr-2"></i> 插入砖块
121
+ </h3>
122
+ <div class="space-y-4">
123
+ <div>
124
+ <label class="block text-sm font-medium text-gray-700 mb-1">位置索引</label>
125
+ <input v-model="insertIndex" type="number" min="0" placeholder="输入要插入的位置"
126
+ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none transition-custom">
127
+ </div>
128
+ <div>
129
+ <label class="block text-sm font-medium text-gray-700 mb-1">方向角度</label>
130
+ <input v-model="insertDirection" type="number" min="0" max="359" placeholder="输入方向角度"
131
+ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none transition-custom">
132
+ </div>
133
+ <button @click="insertFloor" :disabled="!hasFile"
134
+ class="w-full bg-primary text-white px-4 py-2 rounded-lg font-medium hover:bg-primary/90 transition-custom shadow-md hover:shadow-lg">
135
+ 执行插入
136
+ </button>
137
+ </div>
138
+ </div>
139
+
140
+ <!-- 追加砖块 -->
141
+ <div class="bg-gray-50 rounded-lg p-5 border-l-4 border-accent transition-custom hover:shadow-md">
142
+ <h3 class="font-semibold text-lg mb-4 flex items-center">
143
+ <i class="fa fa-arrow-down text-accent mr-2"></i> 追加砖块
144
+ </h3>
145
+ <div class="space-y-4">
146
+ <div>
147
+ <label class="block text-sm font-medium text-gray-700 mb-1">方向角度</label>
148
+ <input v-model="appendDirection" type="number" min="0" max="359" placeholder="输入方向角度"
149
+ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-accent/50 focus:border-accent outline-none transition-custom">
150
+ </div>
151
+ <button @click="appendFloor" :disabled="!hasFile"
152
+ class="w-full bg-accent text-white px-4 py-2 rounded-lg font-medium hover:bg-accent/90 transition-custom shadow-md hover:shadow-lg">
153
+ 执行追加
154
+ </button>
155
+ </div>
156
+ </div>
157
+
158
+ <!-- 删除砖块 -->
159
+ <div class="bg-gray-50 rounded-lg p-5 border-l-4 border-red-500 transition-custom hover:shadow-md">
160
+ <h3 class="font-semibold text-lg mb-4 flex items-center">
161
+ <i class="fa fa-trash text-red-500 mr-2"></i> 删除砖块
162
+ </h3>
163
+ <div class="space-y-4">
164
+ <div>
165
+ <label class="block text-sm font-medium text-gray-700 mb-1">位置索引</label>
166
+ <input v-model="deleteIndex" type="number" min="0" placeholder="输入要删除的位置"
167
+ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-red-500/50 focus:border-red-500 outline-none transition-custom">
168
+ </div>
169
+ <button @click="deleteFloor" :disabled="!hasFile"
170
+ class="w-full bg-red-500 text-white px-4 py-2 rounded-lg font-medium hover:bg-red-600 transition-custom shadow-md hover:shadow-lg">
171
+ 执行删除
172
+ </button>
173
+ </div>
174
+ </div>
175
+ </div>
176
+ </div>
177
+ </section>
178
+
179
+ <!-- 实时预览区 -->
180
+ <section>
181
+ <div class="bg-white rounded-xl p-6 card-shadow">
182
+ <div class="flex justify-between items-center mb-4">
183
+ <h2 class="text-xl font-bold flex items-center text-primary">
184
+ <i class="fa fa-code mr-2"></i> 实时预览
185
+ </h2>
186
+ <div class="flex space-x-2">
187
+ <button id="copyCode"
188
+ class="bg-gray-100 text-gray-700 px-3 py-1 rounded-lg text-sm hover:bg-gray-200 transition-custom flex items-center">
189
+ <i class="fa fa-copy mr-1"></i> 复制
190
+ </button>
191
+ <button id="downloadCode"
192
+ class="bg-gray-100 text-gray-700 px-3 py-1 rounded-lg text-sm hover:bg-gray-200 transition-custom flex items-center">
193
+ <i class="fa fa-download mr-1"></i> 下载
194
+ </button>
195
+ </div>
196
+ </div>
197
+ <div id="editor" style="height: 500px; border: 1px solid #e2e8f0; border-radius: 0.5rem;"></div>
198
+ </div>
199
+ </section>
200
+ </main>
201
+
202
+ <!-- 页脚 -->
203
+ <footer class="bg-dark text-white py-6">
204
+ <div class="container mx-auto px-4">
205
+ <div class="flex flex-col md:flex-row justify-between items-center">
206
+ <div class="mb-4 md:mb-0">
207
+ <p class="text-sm">© 2023 ADOFAI 编辑器 | 一个简洁的ADOFAI文件编辑工具</p>
208
+ </div>
209
+ <div class="flex space-x-4">
210
+ <a href="#" class="text-gray-400 hover:text-white transition-custom">
211
+ <i class="fa fa-github text-xl"></i>
212
+ </a>
213
+ <a href="#" class="text-gray-400 hover:text-white transition-custom">
214
+ <i class="fa fa-twitter text-xl"></i>
215
+ </a>
216
+ <a href="#" class="text-gray-400 hover:text-white transition-custom">
217
+ <i class="fa fa-envelope text-xl"></i>
218
+ </a>
219
+ </div>
220
+ </div>
221
+ </div>
222
+ </footer>
223
+
224
+ <!-- 提示消息 -->
225
+ <div id="toast"
226
+ class="fixed bottom-4 right-4 bg-dark text-white px-6 py-3 rounded-lg shadow-lg transform translate-y-20 opacity-0 transition-all duration-300 z-50">
227
+ <div class="flex items-center">
228
+ <i id="toastIcon" class="fa fa-check-circle text-green-400 mr-2"></i>
229
+ <span id="toastMessage">操作成功!</span>
230
+ </div>
231
+ </div>
232
+
233
+ <script>
234
+ // 初始化Vue应用
235
+ const app = Vue.createApp({
236
+ data() {
237
+ return {
238
+ // 操作表单数据
239
+ insertIndex: '',
240
+ insertDirection: 90,
241
+ appendDirection: 90,
242
+ deleteIndex: '',
243
+ // 文件状态
244
+ hasFile: false,
245
+ // 编辑器实例
246
+ editor: null,
247
+ };
248
+ },
249
+ mounted() {
250
+ // 初始化文件上传事件
251
+ this.initFileUpload();
252
+
253
+ // 初始化导出按钮事件
254
+ this.initExportButton();
255
+
256
+ // 初始化复制和下载代码按钮
257
+ this.initCodeButtons();
258
+
259
+ // 初始化重置文件按钮
260
+ this.initResetButton();
261
+
262
+ // 初始化编辑器
263
+ this.initEditor();
264
+ },
265
+ methods: {
266
+ // 初始化文件上传
267
+ initFileUpload() {
268
+ const inputFile = document.getElementById('inputFile');
269
+ inputFile.addEventListener('change', (e) => {
270
+ const file = e.target.files[0];
271
+ if (!file) return;
272
+
273
+ // 更新文件信息
274
+ document.getElementById('fileName').textContent = file.name;
275
+ document.getElementById('fileSize').textContent = this.formatFileSize(file.size);
276
+ document.getElementById('fileInfo').classList.remove('hidden');
277
+
278
+ // 读取文件内容
279
+ const reader = new FileReader();
280
+ reader.onload = (event) => {
281
+ try {
282
+ // 假设这里的ADOFAI.Level已经在外部定义
283
+ window.CurADOFAI = new ADOFAI.Level(event.target.result);
284
+ this.hasFile = true;
285
+ window.CurADOFAI.on('load', () => {
286
+
287
+ this.updateEditor();
288
+ this.showToast('文件加载成功!', 'success');
289
+ });
290
+ window.CurADOFAI.load();
291
+
292
+ } catch (error) {
293
+ this.showToast('文件格式错误,请上传有效的ADOFAI文件!', 'error');
294
+ console.error('文件解析错误:', error);
295
+ }
296
+ };
297
+ reader.readAsText(file, 'utf-8');
298
+ });
299
+ },
300
+
301
+ // 初始化导出按钮
302
+ initExportButton() {
303
+ const exportBtn = document.getElementById('exportBtn');
304
+ exportBtn.addEventListener('click', () => {
305
+ if (!window.CurADOFAI) {
306
+ this.showToast('请先上传文件!', 'error');
307
+ return;
308
+ }
309
+
310
+ const blob = new Blob([window.CurADOFAI.export(null, null, 2)], { type: 'text/plain' });
311
+ const url = URL.createObjectURL(blob);
312
+ const a = document.createElement("a");
313
+ a.href = url;
314
+ a.download = "export.adofai";
315
+ a.click();
316
+ URL.revokeObjectURL(url);
317
+
318
+ this.showToast('文件导出成功!', 'success');
319
+ });
320
+ },
321
+
322
+ // 初始化复制和下载代码按钮
323
+ initCodeButtons() {
324
+ // 复制代码
325
+ document.getElementById('copyCode').addEventListener('click', () => {
326
+ if (!window.CurADOFAI) return;
327
+
328
+ const text = window.CurADOFAI.export(null, null, 2);
329
+ navigator.clipboard.writeText(text).then(() => {
330
+ this.showToast('代码已复制到剪贴板!', 'success');
331
+ }).catch(err => {
332
+ console.error('复制失败:', err);
333
+ this.showToast('复制失败,请手动复制!', 'error');
334
+ });
335
+ });
336
+
337
+ // 下载代码
338
+ document.getElementById('downloadCode').addEventListener('click', () => {
339
+ if (!window.CurADOFAI) return;
340
+
341
+ const text = window.CurADOFAI.export(null, null, 2);
342
+ const blob = new Blob([text], { type: 'text/plain' });
343
+ const url = URL.createObjectURL(blob);
344
+ const a = document.createElement("a");
345
+ a.href = url;
346
+ a.download = "adofai_code.txt";
347
+ a.click();
348
+ URL.revokeObjectURL(url);
349
+
350
+ this.showToast('代码已下载!', 'success');
351
+ });
352
+ },
353
+
354
+ // 初始化重置文件按钮
355
+ initResetButton() {
356
+ document.getElementById('resetFile').addEventListener('click', () => {
357
+ document.getElementById('inputFile').value = '';
358
+ document.getElementById('fileInfo').classList.add('hidden');
359
+ window.CurADOFAI = null;
360
+ this.hasFile = false;
361
+ this.editor.setValue('// 请上传ADOFAI文件以查看内容', -1);
362
+ this.showToast('文件已重置!', 'info');
363
+ });
364
+ },
365
+
366
+ // 初始化编辑器
367
+ initEditor() {
368
+ this.editor = ace.edit('editor');
369
+ this.editor.setTheme('ace/theme/monokai');
370
+ this.editor.session.setMode('ace/mode/json');
371
+ this.editor.setOptions({
372
+ fontSize: '14px',
373
+ showPrintMargin: false,
374
+ wrap: true,
375
+ autoScrollEditorIntoView: true,
376
+ enableBasicAutocompletion: true,
377
+ enableLiveAutocompletion: true
378
+ });
379
+
380
+ // 设置初始内容
381
+ this.editor.setValue('// 请上传ADOFAI文件以查看内容', -1);
382
+ },
383
+
384
+ // 更新编辑器内容
385
+ updateEditor() {
386
+ if (window.CurADOFAI) {
387
+ this.editor.setValue(window.CurADOFAI.export(null, null, 2), -1);
388
+ }
389
+ },
390
+
391
+ // 插入砖块
392
+ insertFloor() {
393
+ if (!window.CurADOFAI) return;
394
+
395
+ const index = parseInt(this.insertIndex);
396
+ const direction = parseInt(this.insertDirection);
397
+
398
+ if (isNaN(index) || isNaN(direction)) {
399
+ this.showToast('请输入有效的数字!', 'error');
400
+ return;
401
+ }
402
+
403
+ try {
404
+ window.CurADOFAI.floorOperation({ type: 'insert', id: index, direction });
405
+ this.updateEditor();
406
+ this.showToast(`已在索引 ${index} 后插入砖块!`, 'success');
407
+ } catch (error) {
408
+ this.showToast('插入失败: ' + error.message, 'error');
409
+ console.error('插入砖块错误:', error);
410
+ }
411
+ },
412
+
413
+ // 追加砖块
414
+ appendFloor() {
415
+ if (!window.CurADOFAI) return;
416
+
417
+ const direction = parseInt(this.appendDirection);
418
+
419
+ if (isNaN(direction)) {
420
+ this.showToast('请输入有效的方向角度!', 'error');
421
+ return;
422
+ }
423
+
424
+ try {
425
+ window.CurADOFAI.floorOperation({ type: 'append', direction });
426
+ this.updateEditor();
427
+ this.showToast('已追加新砖块!', 'success');
428
+ } catch (error) {
429
+ this.showToast('追加失败: ' + error.message, 'error');
430
+ console.error('追加砖块错误:', error);
431
+ }
432
+ },
433
+
434
+ // 删除砖块
435
+ deleteFloor() {
436
+ if (!window.CurADOFAI) return;
437
+
438
+ const index = parseInt(this.deleteIndex);
439
+
440
+ if (isNaN(index)) {
441
+ this.showToast('请输入有效的索引!', 'error');
442
+ return;
443
+ }
444
+
445
+ try {
446
+ window.CurADOFAI.floorOperation({ type: 'delete', id: index });
447
+ this.updateEditor();
448
+ this.showToast(`已删除索引 ${index} 的砖块!`, 'success');
449
+ } catch (error) {
450
+ this.showToast('删除失败: ' + error.message, 'error');
451
+ console.error('删除砖块错误:', error);
452
+ }
453
+ },
454
+
455
+ // 显示提示消息
456
+ showToast(message, type = 'info') {
457
+ const toast = document.getElementById('toast');
458
+ const toastMessage = document.getElementById('toastMessage');
459
+ const toastIcon = document.getElementById('toastIcon');
460
+
461
+ // 设置消息内容和图标
462
+ toastMessage.textContent = message;
463
+
464
+ // 根据类型设置图标
465
+ if (type === 'success') {
466
+ toastIcon.className = 'fa fa-check-circle text-green-400 mr-2';
467
+ } else if (type === 'error') {
468
+ toastIcon.className = 'fa fa-exclamation-circle text-red-400 mr-2';
469
+ } else if (type === 'warning') {
470
+ toastIcon.className = 'fa fa-exclamation-triangle text-yellow-400 mr-2';
471
+ } else {
472
+ toastIcon.className = 'fa fa-info-circle text-blue-400 mr-2';
473
+ }
474
+
475
+ // 显示提示
476
+ toast.classList.remove('translate-y-20', 'opacity-0');
477
+ toast.classList.add('translate-y-0', 'opacity-100');
478
+
479
+ // 3秒后隐藏提示
480
+ setTimeout(() => {
481
+ toast.classList.remove('translate-y-0', 'opacity-100');
482
+ toast.classList.add('translate-y-20', 'opacity-0');
483
+ }, 3000);
484
+ },
485
+
486
+ // 格式化文件大小
487
+ formatFileSize(bytes) {
488
+ if (bytes === 0) return '0 Bytes';
489
+ const k = 1024;
490
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
491
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
492
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
493
+ }
494
+ }
495
+ });
496
+
497
+ app.mount('body');
498
+ </script>
499
+ </body>
500
+
501
+ </html>
@@ -0,0 +1,26 @@
1
+ <input type="file" id="inputFile">
2
+ <button id="export">Export as ADOFAI</button>
3
+ <script src="../dist/adofai.min.js"></script>
4
+ <script>
5
+ let fl, reader;
6
+ document.querySelector('#inputFile').addEventListener('change', f => {
7
+ fl = f.target.files[0];
8
+ reader = new FileReader();
9
+ reader.onload = () => {
10
+ const a = new ADOFAI.Level(reader.result);
11
+ window.CurADOFAI = a;
12
+ }
13
+ reader.readAsText(fl, 'utf-8')
14
+
15
+ });
16
+ document.querySelector('#export').addEventListener('click', () => {
17
+ const blob = new Blob([CurADOFAI.export(null,null,2)],{'type':'text/plain'})
18
+ const url = URL.createObjectURL(blob);
19
+ const a = document.createElement("a");
20
+ a.href = url;
21
+ a.download = "export.adofai";
22
+ a.click();
23
+ URL.revokeObjectURL(url);
24
+
25
+ })
26
+ </script>
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2016",
4
+ "module": "commonjs",
5
+ "esModuleInterop": true,
6
+ "forceConsistentCasingInFileNames": true,
7
+ "strict": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "./dist",
10
+ "rootDir": "./",
11
+ "declaration": true,
12
+ "sourceMap": true,
13
+ "moduleResolution": "node"
14
+ },
15
+ "include": ["src/**/*", "index.ts"],
16
+ "exclude": ["node_modules", "dist"]
17
+ }
@@ -0,0 +1,35 @@
1
+ import path from 'path'
2
+
3
+ export default {
4
+ entry: './index.ts',
5
+ output: {
6
+ library: {
7
+ name: 'ADOFAI',
8
+ type: 'umd'
9
+ },
10
+ globalObject: 'globalThis',
11
+ filename: 'index.js',
12
+ path: path.resolve('dist')
13
+ },
14
+ module: {
15
+ rules: [
16
+ {
17
+ test: /\.tsx?$/,
18
+ exclude: /node_modules/,
19
+ use: [
20
+ {
21
+ loader: 'babel-loader'
22
+ },
23
+ {
24
+ loader: 'ts-loader'
25
+ }
26
+ ]
27
+ }
28
+ ]
29
+ },
30
+ resolve: {
31
+ extensions: ['.ts', '.tsx', '.js', '.jsx']
32
+ },
33
+ mode: 'production'
34
+ //mode:'development'
35
+ };