import keyword from 'emojis-keywords'; import list from 'emojis-list'; import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; import qface from 'qface'; import { api, gql } from 'vj/utils'; function emoji(range) { return keyword.map((i, index) => ({ label: `${list[index]} ${i}`, kind: monaco.languages.CompletionItemKind.Keyword, documentation: i, insertText: list[index], range, })); } function qqEmoji(range) { return qface.data.flatMap((i) => { const url = qface.getUrl(i.QSid, 'https://qq-face.vercel.app'); return i.Input.map((input) => ({ label: `/${input}`, kind: monaco.languages.CompletionItemKind.Keyword, documentation: { value: `![${i.QDes}](${url})`, isTrusted: true }, insertText: `![${i.Input[0]}](${url} =32x32) `, range, })); }); } monaco.editor.registerCommand('hydro.openUserPage', (accesser, uid) => { window.open(`/user/${uid}`); }); monaco.languages.registerCodeLensProvider('markdown', { async provideCodeLenses(model) { const users = model.findMatches('\\[\\]\\(/user/(\\d+)\\)', true, true, true, null, true); if (!users.length) { return { lenses: [], dispose: () => { }, }; } const { data } = await api(gql` users(ids: ${users.map((i) => +i.matches[1])}) { _id uname } `); return { lenses: users.map((i, index) => ({ range: i.range, id: `${index}.${i.matches[1]}`, command: { id: 'hydro.openUserPage', arguments: [i.matches[1]], title: `@${data.users.find((doc) => doc._id.toString() === i.matches[1])?.uname || i.matches[1]}`, }, })), dispose: () => { }, }; }, resolveCodeLens(model, codeLens) { return codeLens; }, }); monaco.languages.registerCompletionItemProvider('markdown', { async provideCompletionItems(model, position) { const word = model.getWordAtPosition(position); if (word.word.length < 2) return { suggestions: [] }; const prefix = model.getValueInRange({ startLineNumber: position.lineNumber, endLineNumber: position.lineNumber, startColumn: word.startColumn - 1, endColumn: word.startColumn, }); if (![':', '/', '@'].includes(prefix)) return { suggestions: [] }; const range = { startLineNumber: position.lineNumber, endLineNumber: position.lineNumber, startColumn: word.startColumn - 1, endColumn: word.endColumn, }; if (prefix === '@') { const users = await api(gql` users(search: ${word.word}) { _id uname avatarUrl priv } `, ['data', 'users']); return { suggestions: users.map((i) => ({ label: { label: `@${i.uname}`, description: `UID=${i._id}` }, kind: monaco.languages.CompletionItemKind.Property, documentation: { value: `[](#loader) ![avatar](${new URL(i.avatarUrl, window.location.href)})`, isTrusted: true }, insertText: `@[](/user/${i._id}) `, range, sortText: i.priv === 0 ? '0' : '1', tags: i.priv === 0 ? [1] : [], })), }; } return { suggestions: prefix === ':' ? emoji(range) : qqEmoji(range), }; }, });