parent
							
								
									debc0086fa
								
							
						
					
					
						commit
						9b73e897df
					
				|  | @ -523,6 +523,9 @@ themeEditor: "テーマエディター" | |||
| description: "説明" | ||||
| author: "作者" | ||||
| leaveConfirm: "未保存の変更があります。破棄しますか?" | ||||
| manage: "管理" | ||||
| plugins: "プラグイン" | ||||
| pluginInstallWarn: "信頼できないプラグインはインストールしないでください。" | ||||
| deck: "デッキ" | ||||
| undeck: "デッキ解除" | ||||
| 
 | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ | |||
| 		"@koa/multer": "3.0.0", | ||||
| 		"@koa/router": "9.3.1", | ||||
| 		"@sinonjs/fake-timers": "6.0.1", | ||||
| 		"@syuilo/aiscript": "0.7.0", | ||||
| 		"@syuilo/aiscript": "0.7.2", | ||||
| 		"@types/bcryptjs": "2.4.2", | ||||
| 		"@types/bull": "3.14.0", | ||||
| 		"@types/cbor": "5.0.0", | ||||
|  |  | |||
|  | @ -89,7 +89,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faBolt, faTimes, faBullhorn, faStar, faLink, faExternalLinkSquareAlt, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faQuoteRight, faInfoCircle, faBiohazard, faEllipsisH } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faBolt, faTimes, faBullhorn, faStar, faLink, faExternalLinkSquareAlt, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faQuoteRight, faInfoCircle, faBiohazard, faPlug } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faCopy, faTrashAlt, faEdit, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons'; | ||||
| import { parse } from '../../mfm/parse'; | ||||
| import { sum, unique } from '../../prelude/array'; | ||||
|  | @ -108,7 +108,6 @@ import { url } from '../config'; | |||
| import copyToClipboard from '../scripts/copy-to-clipboard'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	 | ||||
| 	components: { | ||||
| 		XSub, | ||||
| 		XNoteHeader, | ||||
|  | @ -145,7 +144,7 @@ export default Vue.extend({ | |||
| 			showContent: false, | ||||
| 			hideThisNote: false, | ||||
| 			noteBody: this.$refs.noteBody, | ||||
| 			faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faBiohazard, faEllipsisH | ||||
| 			faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faBiohazard, faPlug | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -612,6 +611,16 @@ export default Vue.extend({ | |||
| 				.filter(x => x !== undefined); | ||||
| 			} | ||||
| 
 | ||||
| 			if (this.$store.state.noteActions.length > 0) { | ||||
| 				menu = menu.concat([null, ...this.$store.state.noteActions.map(action => ({ | ||||
| 					icon: faPlug, | ||||
| 					text: action.title, | ||||
| 					action: () => { | ||||
| 						action.handler(this.appearNote); | ||||
| 					} | ||||
| 				}))]); | ||||
| 			} | ||||
| 
 | ||||
| 			this.$root.menu({ | ||||
| 				items: menu, | ||||
| 				source: this.$refs.menuButton, | ||||
|  |  | |||
|  | @ -44,6 +44,7 @@ | |||
| 			<button class="_button" @click="useCw = !useCw" :class="{ active: useCw }" v-tooltip="$t('useCw')"><fa :icon="faEyeSlash"/></button> | ||||
| 			<button class="_button" @click="insertMention" v-tooltip="$t('mention')"><fa :icon="faAt"/></button> | ||||
| 			<button class="_button" @click="insertEmoji" v-tooltip="$t('emoji')"><fa :icon="faLaughSquint"/></button> | ||||
| 			<button class="_button" @click="showActions" v-tooltip="$t('plugin')" v-if="$store.state.postFormActions.length > 0"><fa :icon="faPlug"/></button> | ||||
| 		</footer> | ||||
| 		<input ref="file" class="file _button" type="file" multiple="multiple" @change="onChangeFile"/> | ||||
| 	</div> | ||||
|  | @ -52,7 +53,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faReply, faQuoteRight, faPaperPlane, faTimes, faUpload, faPollH, faGlobe, faHome, faUnlock, faEnvelope, faPlus, faPhotoVideo, faCloud, faLink, faAt, faBiohazard } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faReply, faQuoteRight, faPaperPlane, faTimes, faUpload, faPollH, faGlobe, faHome, faUnlock, faEnvelope, faPlus, faPhotoVideo, faCloud, faLink, faAt, faBiohazard, faPlug } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faEyeSlash, faLaughSquint } from '@fortawesome/free-regular-svg-icons'; | ||||
| import insertTextAtCursor from 'insert-text-at-cursor'; | ||||
| import { length } from 'stringz'; | ||||
|  | @ -133,7 +134,7 @@ export default Vue.extend({ | |||
| 			draghover: false, | ||||
| 			quoteId: null, | ||||
| 			recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'), | ||||
| 			faReply, faQuoteRight, faPaperPlane, faTimes, faUpload, faPollH, faGlobe, faHome, faUnlock, faEnvelope, faEyeSlash, faLaughSquint, faPlus, faPhotoVideo, faCloud, faLink, faAt, faBiohazard | ||||
| 			faReply, faQuoteRight, faPaperPlane, faTimes, faUpload, faPollH, faGlobe, faHome, faUnlock, faEnvelope, faEyeSlash, faLaughSquint, faPlus, faPhotoVideo, faCloud, faLink, faAt, faBiohazard, faPlug | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -580,6 +581,22 @@ export default Vue.extend({ | |||
| 				vm.close(); | ||||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		showActions(ev) { | ||||
| 			this.$root.menu({ | ||||
| 				items: this.$store.state.postFormActions.map(action => ({ | ||||
| 					text: action.title, | ||||
| 					action: () => { | ||||
| 						action.handler({ | ||||
| 							text: this.text | ||||
| 						}, (key, value) => { | ||||
| 							if (key === 'text') { this.text = value; } | ||||
| 						}); | ||||
| 					} | ||||
| 				})), | ||||
| 				source: ev.currentTarget || ev.target, | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faAt, faListUl, faEye, faEyeSlash, faBan, faPencilAlt, faComments, faUsers, faMicrophoneSlash } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faAt, faListUl, faEye, faEyeSlash, faBan, faPencilAlt, faComments, faUsers, faMicrophoneSlash, faPlug } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faSnowflake, faEnvelope } from '@fortawesome/free-regular-svg-icons'; | ||||
| import XMenu from './menu.vue'; | ||||
| import copyToClipboard from '../scripts/copy-to-clipboard'; | ||||
|  | @ -80,6 +80,16 @@ export default Vue.extend({ | |||
| 			}]); | ||||
| 		} | ||||
| 
 | ||||
| 		if (this.$store.state.userActions.length > 0) { | ||||
| 			menu = menu.concat([null, ...this.$store.state.userActions.map(action => ({ | ||||
| 				icon: faPlug, | ||||
| 				text: action.title, | ||||
| 				action: () => { | ||||
| 					action.handler(this.user); | ||||
| 				} | ||||
| 			}))]); | ||||
| 		} | ||||
| 
 | ||||
| 		return { | ||||
| 			items: menu | ||||
| 		}; | ||||
|  |  | |||
|  | @ -25,6 +25,8 @@ import { isDeviceDarkmode } from './scripts/is-device-darkmode'; | |||
| import createStore from './store'; | ||||
| import { clientDb, get, count } from './db'; | ||||
| import { setI18nContexts } from './scripts/set-i18n-contexts'; | ||||
| import { createPluginEnv } from './scripts/aiscript/api'; | ||||
| import { AiScript } from '@syuilo/aiscript'; | ||||
| 
 | ||||
| Vue.use(Vuex); | ||||
| Vue.use(VueHotkey); | ||||
|  | @ -231,6 +233,35 @@ os.init(async () => { | |||
| 		//store.commit('instance/set', );
 | ||||
| 	}); | ||||
| 
 | ||||
| 	for (const plugin of store.state.deviceUser.plugins) { | ||||
| 		console.info('Plugin installed:', plugin.name, 'v' + plugin.version); | ||||
| 
 | ||||
| 		const aiscript = new AiScript(createPluginEnv(app, { | ||||
| 			plugin: plugin, | ||||
| 			storageKey: 'plugins:' + plugin.id | ||||
| 		}), { | ||||
| 			in: (q) => { | ||||
| 				return new Promise(ok => { | ||||
| 					app.dialog({ | ||||
| 						title: q, | ||||
| 						input: {} | ||||
| 					}).then(({ canceled, result: a }) => { | ||||
| 						ok(a); | ||||
| 					}); | ||||
| 				}); | ||||
| 			}, | ||||
| 			out: (value) => { | ||||
| 				console.log(value); | ||||
| 			}, | ||||
| 			log: (type, params) => { | ||||
| 			}, | ||||
| 		}); | ||||
| 
 | ||||
| 		store.commit('initPlugin', { plugin, aiscript }); | ||||
| 
 | ||||
| 		aiscript.exec(plugin.ast); | ||||
| 	} | ||||
| 
 | ||||
| 	if (store.getters.isSignedIn) { | ||||
| 		const main = os.stream.useSharedConnection('main'); | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ | |||
| 
 | ||||
| 	<x-sidebar/> | ||||
| 
 | ||||
| 	<x-plugins/> | ||||
| 
 | ||||
| 	<section class="_card"> | ||||
| 		<div class="_title"><fa :icon="faMusic"/> {{ $t('sounds') }}</div> | ||||
| 		<div class="_content"> | ||||
|  | @ -115,6 +117,7 @@ import MkRadio from '../../components/ui/radio.vue'; | |||
| import MkRange from '../../components/ui/range.vue'; | ||||
| import XTheme from './theme.vue'; | ||||
| import XSidebar from './sidebar.vue'; | ||||
| import XPlugins from './plugins.vue'; | ||||
| import { langs } from '../../config'; | ||||
| import { clientDb, set } from '../../db'; | ||||
| 
 | ||||
|  | @ -146,11 +149,12 @@ export default Vue.extend({ | |||
| 	components: { | ||||
| 		XTheme, | ||||
| 		XSidebar, | ||||
| 		XPlugins, | ||||
| 		MkButton, | ||||
| 		MkSwitch, | ||||
| 		MkSelect, | ||||
| 		MkRadio, | ||||
| 		MkRange | ||||
| 		MkRange, | ||||
| 	}, | ||||
| 
 | ||||
| 	data() { | ||||
|  |  | |||
|  | @ -0,0 +1,134 @@ | |||
| <template> | ||||
| <section class="_card"> | ||||
| 	<div class="_title"><fa :icon="faPlug"/> {{ $t('plugins') }}</div> | ||||
| 	<div class="_content"> | ||||
| 		<details> | ||||
| 			<summary><fa :icon="faDownload"/> {{ $t('install') }}</summary> | ||||
| 			<mk-info warn>{{ $t('pluginInstallWarn') }}</mk-info> | ||||
| 			<mk-textarea v-model="script" tall> | ||||
| 				<span>{{ $t('script') }}</span> | ||||
| 			</mk-textarea> | ||||
| 			<mk-button @click="install()" primary><fa :icon="faSave"/> {{ $t('install') }}</mk-button> | ||||
| 		</details> | ||||
| 	</div> | ||||
| 	<div class="_content"> | ||||
| 		<details> | ||||
| 			<summary><fa :icon="faFolderOpen"/> {{ $t('manage') }}</summary> | ||||
| 			<mk-select v-model="selectedPluginId"> | ||||
| 				<option v-for="x in $store.state.deviceUser.plugins" :value="x.id" :key="x.id">{{ x.name }}</option> | ||||
| 			</mk-select> | ||||
| 			<template v-if="selectedPlugin"> | ||||
| 				<div class="_keyValue"> | ||||
| 					<div>{{ $t('version') }}:</div> | ||||
| 					<div>{{ selectedPlugin.version }}</div> | ||||
| 				</div> | ||||
| 				<div class="_keyValue"> | ||||
| 					<div>{{ $t('author') }}:</div> | ||||
| 					<div>{{ selectedPlugin.author }}</div> | ||||
| 				</div> | ||||
| 				<div class="_keyValue"> | ||||
| 					<div>{{ $t('description') }}:</div> | ||||
| 					<div>{{ selectedPlugin.description }}</div> | ||||
| 				</div> | ||||
| 				<mk-button @click="uninstall()" style="margin-top: 8px;"><fa :icon="faTrashAlt"/> {{ $t('uninstall') }}</mk-button> | ||||
| 			</template> | ||||
| 		</details> | ||||
| 	</div> | ||||
| </section> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faPlug, faSave, faTrashAlt, faFolderOpen, faDownload } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import MkTextarea from '../../components/ui/textarea.vue'; | ||||
| import MkSelect from '../../components/ui/select.vue'; | ||||
| import MkInfo from '../../components/ui/info.vue'; | ||||
| import { AiScript, parse } from '@syuilo/aiscript'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 		MkTextarea, | ||||
| 		MkSelect, | ||||
| 		MkInfo, | ||||
| 	}, | ||||
| 	 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			script: '', | ||||
| 			selectedPluginId: null, | ||||
| 			faPlug, faSave, faTrashAlt, faFolderOpen, faDownload | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	computed: { | ||||
| 		selectedPlugin() { | ||||
| 			if (this.selectedPluginId == null) return null; | ||||
| 			return this.$store.state.deviceUser.plugins.find(x => x.id === this.selectedPluginId); | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		install() { | ||||
| 			let ast; | ||||
| 			try { | ||||
| 				ast = parse(this.script); | ||||
| 			} catch (e) { | ||||
| 				this.$root.dialog({ | ||||
| 					type: 'error', | ||||
| 					text: 'Syntax error :(' | ||||
| 				}); | ||||
| 				return; | ||||
| 			} | ||||
| 			const meta = AiScript.collectMetadata(ast); | ||||
| 			console.log(meta); | ||||
| 			if (meta == null) { | ||||
| 				this.$root.dialog({ | ||||
| 					type: 'error', | ||||
| 					text: 'No metadata found :(' | ||||
| 				}); | ||||
| 				return; | ||||
| 			} | ||||
| 			const data = meta.get(null); | ||||
| 			if (data == null) { | ||||
| 				this.$root.dialog({ | ||||
| 					type: 'error', | ||||
| 					text: 'No metadata found :(' | ||||
| 				}); | ||||
| 				return; | ||||
| 			} | ||||
| 			const { id, name, version, author, description } = data; | ||||
| 			if (id == null || name == null || version == null || author == null) { | ||||
| 				this.$root.dialog({ | ||||
| 					type: 'error', | ||||
| 					text: 'Required property not found :(' | ||||
| 				}); | ||||
| 				return; | ||||
| 			} | ||||
| 			this.$store.commit('deviceUser/installPlugin', { | ||||
| 				meta: { | ||||
| 					id, name, version, author, description | ||||
| 				}, | ||||
| 				ast | ||||
| 			}); | ||||
| 			this.$root.dialog({ | ||||
| 				type: 'success', | ||||
| 				iconOnly: true, autoClose: true | ||||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		uninstall() { | ||||
| 			this.$store.commit('deviceUser/uninstallPlugin', this.selectedPluginId); | ||||
| 			this.$root.dialog({ | ||||
| 				type: 'success', | ||||
| 				iconOnly: true, autoClose: true | ||||
| 			}); | ||||
| 		} | ||||
| 	}, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| 
 | ||||
| </style> | ||||
|  | @ -30,7 +30,7 @@ import PrismEditor from 'vue-prism-editor'; | |||
| import { AiScript, parse, utils, values } from '@syuilo/aiscript'; | ||||
| import MkContainer from '../components/ui/container.vue'; | ||||
| import MkButton from '../components/ui/button.vue'; | ||||
| import { createAiScriptEnv } from '../scripts/create-aiscript-env'; | ||||
| import { createAiScriptEnv } from '../scripts/aiscript/api'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	metaInfo() { | ||||
|  |  | |||
|  | @ -40,3 +40,18 @@ export function createAiScriptEnv(vm, opts) { | |||
| 		}), | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| export function createPluginEnv(vm, opts) { | ||||
| 	return { | ||||
| 		...createAiScriptEnv(vm, opts), | ||||
| 		'Mk:register_post_form_action': values.FN_NATIVE(([title, handler]) => { | ||||
| 			vm.$store.commit('registerPostFormAction', { pluginId: opts.plugin.id, title: title.value, handler }); | ||||
| 		}), | ||||
| 		'Mk:register_user_action': values.FN_NATIVE(([title, handler]) => { | ||||
| 			vm.$store.commit('registerUserAction', { pluginId: opts.plugin.id, title: title.value, handler }); | ||||
| 		}), | ||||
| 		'Mk:register_note_action': values.FN_NATIVE(([title, handler]) => { | ||||
| 			vm.$store.commit('registerNoteAction', { pluginId: opts.plugin.id, title: title.value, handler }); | ||||
| 		}), | ||||
| 	}; | ||||
| } | ||||
|  | @ -3,7 +3,7 @@ import * as seedrandom from 'seedrandom'; | |||
| import { Variable, PageVar, envVarsDef, funcDefs, Block, isFnBlock } from '.'; | ||||
| import { version } from '../../config'; | ||||
| import { AiScript, utils, values } from '@syuilo/aiscript'; | ||||
| import { createAiScriptEnv } from '../create-aiscript-env'; | ||||
| import { createAiScriptEnv } from '../aiscript/api'; | ||||
| import { collectPageVars } from '../collect-page-vars'; | ||||
| import { initLib } from './lib'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ import createPersistedState from 'vuex-persistedstate'; | |||
| import * as nestedProperty from 'nested-property'; | ||||
| import { faTerminal, faHashtag, faBroadcastTower, faFireAlt, faSearch, faStar, faAt, faListUl, faUserClock, faUsers, faCloud, faGamepad, faFileAlt, faSatellite, faDoorClosed, faColumns } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faBell, faEnvelope, faComments } from '@fortawesome/free-regular-svg-icons'; | ||||
| import { AiScript, utils, values } from '@syuilo/aiscript'; | ||||
| import { apiUrl, deckmode } from './config'; | ||||
| import { erase } from '../prelude/array'; | ||||
| 
 | ||||
|  | @ -43,6 +44,7 @@ export const defaultDeviceUserSettings = { | |||
| 		columns: [], | ||||
| 		layout: [], | ||||
| 	}, | ||||
| 	plugins: [], | ||||
| }; | ||||
| 
 | ||||
| export const defaultDeviceSettings = { | ||||
|  | @ -93,7 +95,13 @@ export default () => new Vuex.Store({ | |||
| 	state: { | ||||
| 		i: null, | ||||
| 		pendingApiRequestsCount: 0, | ||||
| 		spinner: null | ||||
| 		spinner: null, | ||||
| 
 | ||||
| 		// Plugin
 | ||||
| 		pluginContexts: new Map<string, AiScript>(), | ||||
| 		postFormActions: [], | ||||
| 		userActions: [], | ||||
| 		noteActions: [], | ||||
| 	}, | ||||
| 
 | ||||
| 	getters: { | ||||
|  | @ -224,8 +232,38 @@ export default () => new Vuex.Store({ | |||
| 			state.i = x; | ||||
| 		}, | ||||
| 
 | ||||
| 		updateIKeyValue(state, x) { | ||||
| 			state.i[x.key] = x.value; | ||||
| 		updateIKeyValue(state, { key, value }) { | ||||
| 			state.i[key] = value; | ||||
| 		}, | ||||
| 
 | ||||
| 		initPlugin(state, { plugin, aiscript }) { | ||||
| 			state.pluginContexts.set(plugin.id, aiscript); | ||||
| 		}, | ||||
| 
 | ||||
| 		registerPostFormAction(state, { pluginId, title, handler }) { | ||||
| 			state.postFormActions.push({ | ||||
| 				title, handler: (form, update) => { | ||||
| 					state.pluginContexts.get(pluginId).execFn(handler, [utils.jsToVal(form), values.FN_NATIVE(([key, value]) => { | ||||
| 						update(key.value, value.value); | ||||
| 					})]); | ||||
| 				} | ||||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		registerUserAction(state, { pluginId, title, handler }) { | ||||
| 			state.userActions.push({ | ||||
| 				title, handler: (user) => { | ||||
| 					state.pluginContexts.get(pluginId).execFn(handler, [utils.jsToVal(user)]); | ||||
| 				} | ||||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		registerNoteAction(state, { pluginId, title, handler }) { | ||||
| 			state.noteActions.push({ | ||||
| 				title, handler: (note) => { | ||||
| 					state.pluginContexts.get(pluginId).execFn(handler, [utils.jsToVal(note)]); | ||||
| 				} | ||||
| 			}); | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -546,6 +584,21 @@ export default () => new Vuex.Store({ | |||
| 					column = x; | ||||
| 				}, | ||||
| 				//#endregion
 | ||||
| 
 | ||||
| 				installPlugin(state, { meta, ast }) { | ||||
| 					state.plugins.push({ | ||||
| 						id: meta.id, | ||||
| 						name: meta.name, | ||||
| 						version: meta.version, | ||||
| 						author: meta.author, | ||||
| 						description: meta.description, | ||||
| 						ast: ast | ||||
| 					}); | ||||
| 				}, | ||||
| 
 | ||||
| 				uninstallPlugin(state, id) { | ||||
| 					state.plugins = state.plugins.filter(x => x.id != id); | ||||
| 				}, | ||||
| 			} | ||||
| 		}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -197,10 +197,10 @@ | |||
|   dependencies: | ||||
|     "@sinonjs/commons" "^1.7.0" | ||||
| 
 | ||||
| "@syuilo/aiscript@0.7.0": | ||||
|   version "0.7.0" | ||||
|   resolved "https://registry.yarnpkg.com/@syuilo/aiscript/-/aiscript-0.7.0.tgz#1394511a789891e844d32e536a203fe0d92b3039" | ||||
|   integrity sha512-X4TaP/FO7RD8MpFSPDFwKAI4KX7byn8ApqmSSmf2bxcwCTcdevsbyxsLrvkbNaWclIoqTgXwtJjY+2Tc2exeXA== | ||||
| "@syuilo/aiscript@0.7.2": | ||||
|   version "0.7.2" | ||||
|   resolved "https://registry.yarnpkg.com/@syuilo/aiscript/-/aiscript-0.7.2.tgz#2f30adb14ffa9f1180af83c059927ab306b175a5" | ||||
|   integrity sha512-l8HVTJTq9KLzDqGswOIGlBepkacudUp70EScrLjL7nEL2NKcti7Ui5fwZCrmxazxgGz6NrVNX5UBIOFFyrwr0A== | ||||
|   dependencies: | ||||
|     autobind-decorator "2.4.0" | ||||
|     chalk "4.0.0" | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue