Browse Source

feat: add create element block

Ahmad Kholid 2 years ago
parent
commit
52aae62c1c

+ 2 - 0
package.json

@@ -31,6 +31,8 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@braks/vue-flow": "^0.4.30",
     "@braks/vue-flow": "^0.4.30",
+    "@codemirror/lang-css": "^6.0.0",
+    "@codemirror/lang-html": "^6.1.0",
     "@codemirror/lang-javascript": "^6.0.0",
     "@codemirror/lang-javascript": "^6.0.0",
     "@codemirror/lang-json": "^6.0.0",
     "@codemirror/lang-json": "^6.0.0",
     "@codemirror/language": "^6.0.0",
     "@codemirror/language": "^6.0.0",

+ 0 - 1
src/background/index.js

@@ -552,7 +552,6 @@ message.on('workflow:execute', (workflowData, sender) => {
 
 
     workflowData.options.tabId = sender.tab.id;
     workflowData.options.tabId = sender.tab.id;
   }
   }
-  console.log(workflowData, 'anu');
 
 
   workflow.execute(workflowData, workflowData?.options || {});
   workflow.execute(workflowData, workflowData?.options || {});
 });
 });

+ 38 - 0
src/background/workflowEngine/blocksHandler/handlerCreateElement.js

@@ -0,0 +1,38 @@
+async function handleCreateElement(block, { refData }) {
+  if (!this.activeTab.id) throw new Error('no-tab');
+
+  const { data } = block;
+  const preloadScriptsPromise = await Promise.allSettled(
+    data.preloadScripts.map((item) => {
+      if (!item.src.startsWith('http'))
+        return Promise.reject(new Error('Invalid URL'));
+
+      return fetch(item.src)
+        .then((response) => response.text())
+        .then((result) => ({ type: item.type, script: result }));
+    })
+  );
+  const preloadScripts = preloadScriptsPromise.reduce((acc, item) => {
+    if (item.status === 'rejected') return acc;
+
+    acc.push(item.value);
+
+    return acc;
+  }, []);
+
+  data.preloadScripts = preloadScripts;
+
+  const payload = { ...block, data, refData: { variables: {} } };
+  if (data.javascript.includes('automaRefData')) {
+    payload.refData = { ...refData, secrets: {} };
+  }
+
+  await this._sendMessageToTab(payload);
+
+  return {
+    data: '',
+    nextBlockId: this.getBlockConnections(block.id),
+  };
+}
+
+export default handleCreateElement;

+ 8 - 27
src/components/newtab/shared/SharedCodemirror.vue

@@ -13,16 +13,16 @@
 </template>
 </template>
 <script setup>
 <script setup>
 import { onMounted, ref, onBeforeUnmount, watch } from 'vue';
 import { onMounted, ref, onBeforeUnmount, watch } from 'vue';
+import { keymap } from '@codemirror/view';
+import { css } from '@codemirror/lang-css';
 import { json } from '@codemirror/lang-json';
 import { json } from '@codemirror/lang-json';
+import { html } from '@codemirror/lang-html';
+import { EditorState } from '@codemirror/state';
+import { EditorView, basicSetup } from 'codemirror';
 import { indentWithTab } from '@codemirror/commands';
 import { indentWithTab } from '@codemirror/commands';
 import { oneDark } from '@codemirror/theme-one-dark';
 import { oneDark } from '@codemirror/theme-one-dark';
-import { keymap } from '@codemirror/view';
 import { javascript } from '@codemirror/lang-javascript';
 import { javascript } from '@codemirror/lang-javascript';
-import { EditorState } from '@codemirror/state';
-import { EditorView, basicSetup } from 'codemirror';
-import { format } from 'prettier';
 import { store } from '../settings/jsBlockWrap';
 import { store } from '../settings/jsBlockWrap';
-import parserBabel from './parser-babel.mjs';
 
 
 const props = defineProps({
 const props = defineProps({
   lang: {
   lang: {
@@ -49,6 +49,8 @@ const props = defineProps({
 const emit = defineEmits(['change', 'update:modelValue']);
 const emit = defineEmits(['change', 'update:modelValue']);
 
 
 let view = null;
 let view = null;
+const langs = { json, javascript, html, css };
+
 const containerEl = ref(null);
 const containerEl = ref(null);
 
 
 const updateListener = EditorView.updateListener.of((event) => {
 const updateListener = EditorView.updateListener.of((event) => {
@@ -71,10 +73,10 @@ const state = EditorState.create({
     oneDark,
     oneDark,
     basicSetup,
     basicSetup,
     updateListener,
     updateListener,
+    langs[props.lang]?.(),
     EditorState.tabSize.of(2),
     EditorState.tabSize.of(2),
     keymap.of([indentWithTab]),
     keymap.of([indentWithTab]),
     EditorState.readOnly.of(props.readonly),
     EditorState.readOnly.of(props.readonly),
-    props.lang === 'javascript' ? javascript() : json(),
     ...customExtension,
     ...customExtension,
   ],
   ],
 });
 });
@@ -99,27 +101,6 @@ onMounted(() => {
 onBeforeUnmount(() => {
 onBeforeUnmount(() => {
   view?.destroy();
   view?.destroy();
 });
 });
-
-let savedStatePrettier = store.statePrettier;
-watch(store, (value) => {
-  if (value.statePrettier !== savedStatePrettier) {
-    // prettier logic here
-    const code = props.modelValue;
-
-    view.dispatch({
-      changes: {
-        from: 0,
-        to: view.state.doc.length,
-        insert: format(code, {
-          parser: 'babel',
-          plugins: [parserBabel],
-        }),
-      },
-    });
-
-    savedStatePrettier = value.statePrettier;
-  }
-});
 </script>
 </script>
 <style>
 <style>
 .cm-content {
 .cm-content {

File diff suppressed because it is too large
+ 0 - 0
src/components/newtab/shared/parser-babel.mjs


+ 198 - 0
src/components/newtab/workflow/edit/EditCreateElement.vue

@@ -0,0 +1,198 @@
+<template>
+  <edit-interaction-base
+    v-bind="{ data }"
+    hide-mark-el
+    hide-multiple
+    @change="updateData"
+  >
+    <ui-select
+      v-model="blockData.insertAt"
+      :label="$t('workflow.blocks.create-element.insertEl.title')"
+      class="w-full mt-4"
+    >
+      <option v-for="item in insertOptions" :key="item" :value="item">
+        {{ $t(`workflow.blocks.create-element.insertEl.items.${item}`) }}
+      </option>
+    </ui-select>
+    <ui-button
+      variant="accent"
+      class="w-full mt-4"
+      @click="state.showModal = true"
+    >
+      {{ $t('workflow.blocks.create-element.edit') }}
+    </ui-button>
+    <ui-modal
+      v-model="state.showModal"
+      content-class="max-w-3xl create-element-modal"
+      padding="p-0"
+    >
+      <template #header>
+        <ui-tabs v-model="state.activeTab" class="border-none space-x-1">
+          <ui-tab v-for="tab in tabs" :key="tab.id" :value="tab.id">
+            {{ tab.name }}
+          </ui-tab>
+          <ui-tab value="preloadScript">
+            {{ $t('workflow.blocks.javascript-code.modal.tabs.preloadScript') }}
+          </ui-tab>
+        </ui-tabs>
+      </template>
+      <ui-tab-panels
+        :model-value="state.activeTab"
+        class="overflow-auto scroll px-4 mb-4"
+        style="height: calc(100vh - 12rem)"
+      >
+        <ui-tab-panel value="html" class="h-full">
+          <div class="flex items-center mb-4">
+            <ui-select
+              v-model="blockData.elementWrapper"
+              :label="$t('workflow.blocks.create-element.wrap')"
+            >
+              <option v-for="item in elementsWrapper" :key="item" :value="item">
+                {{ item.toUpperCase() }} element
+              </option>
+            </ui-select>
+            <ui-input
+              :model-value="`automa-${blockId}`"
+              readonly
+              class="ml-4 w-48"
+              label="Element wrapper id"
+            />
+          </div>
+          <shared-codemirror
+            v-show="['button', 'div'].includes(blockData.elementWrapper)"
+            v-model="blockData.html"
+            lang="html"
+            class="h-full"
+          />
+        </ui-tab-panel>
+        <ui-tab-panel value="css" class="h-full">
+          <shared-codemirror
+            v-model="blockData.css"
+            lang="css"
+            class="h-full"
+          />
+        </ui-tab-panel>
+        <ui-tab-panel value="javascript" class="h-full">
+          <div class="mb-4">
+            <span class="text-sm text-gray-500 dark:text-gray-300">
+              Available functions
+            </span>
+            <div class="flex items-center space-x-2">
+              <a
+                v-for="func in availableFuncs"
+                :key="func.id"
+                :href="`https://docs.automa.site/blocks/javascript-code.html#${func.id}`"
+                target="_blank"
+                rel="noopener"
+                class="inline-block text-sm rounded-md p-1 bg-box-transparent"
+              >
+                <code>
+                  {{ func.name }}
+                </code>
+              </a>
+            </div>
+          </div>
+          <shared-codemirror
+            v-model="blockData.javascript"
+            lang="javascript"
+            class="h-full"
+          />
+        </ui-tab-panel>
+        <ui-tab-panel value="preloadScript">
+          <ul class="my-1 space-y-2">
+            <li
+              v-for="(item, index) in blockData.preloadScripts"
+              :key="index"
+              class="flex items-center space-x-2"
+            >
+              <ui-select v-model="item.type" placeholder="Type">
+                <option value="style">Style</option>
+                <option value="script">Script</option>
+              </ui-select>
+              <ui-input
+                v-model="item.src"
+                :placeholder="`https://example.com/${
+                  item.type === 'style' ? 'style.css' : 'script.js'
+                }`"
+                type="url"
+                class="flex-1"
+              />
+              <v-remixicon
+                name="riDeleteBin7Line"
+                class="cursor-pointer"
+                @click="blockData.preloadScripts.splice(index, 1)"
+              />
+            </li>
+          </ul>
+          <ui-button class="mt-4" @click="addPreloadScript">
+            Add script
+          </ui-button>
+        </ui-tab-panel>
+      </ui-tab-panels>
+    </ui-modal>
+  </edit-interaction-base>
+</template>
+<script setup>
+import { reactive, watch, defineAsyncComponent } from 'vue';
+import cloneDeep from 'lodash.clonedeep';
+import EditInteractionBase from './EditInteractionBase.vue';
+
+const SharedCodemirror = defineAsyncComponent(() =>
+  import('@/components/newtab/shared/SharedCodemirror.vue')
+);
+
+const props = defineProps({
+  data: {
+    type: Object,
+    default: () => ({}),
+  },
+  blockId: {
+    type: String,
+    default: '',
+  },
+});
+const emit = defineEmits(['update:data']);
+
+const availableFuncs = [
+  { name: 'automaRefData(keyword, path?)', id: 'automarefdata-keyword-path' },
+  { name: 'automaExecWorkflow(options)', id: 'automaexecworkflow-options' },
+];
+const insertOptions = [
+  'before',
+  'after',
+  'prev-sibling',
+  'next-sibling',
+  'replace',
+];
+const elementsWrapper = ['div', 'button', 'input', 'textarea'];
+const tabs = [
+  { id: 'html', name: 'HTML' },
+  { id: 'css', name: 'CSS' },
+  { id: 'javascript', name: 'JavaScript' },
+];
+
+const blockData = reactive(cloneDeep(props.data));
+const state = reactive({
+  showModal: false,
+  activeTab: 'html',
+});
+
+function updateData(value) {
+  emit('update:data', { ...props.data, ...value });
+}
+function addPreloadScript() {
+  blockData.preloadScripts.push({
+    src: '',
+    type: 'script',
+  });
+}
+
+watch(blockData, (newValue) => {
+  updateData(newValue);
+});
+</script>
+<style>
+.create-element-modal .modal-ui__content-header {
+  @apply p-4 mb-0;
+}
+</style>

+ 7 - 1
src/components/newtab/workflow/edit/EditInteractionBase.vue

@@ -54,7 +54,9 @@
             {{ t('workflow.blocks.base.multiple.text') }}
             {{ t('workflow.blocks.base.multiple.text') }}
           </ui-checkbox>
           </ui-checkbox>
           <ui-checkbox
           <ui-checkbox
-            v-if="(data.findBy || 'cssSelector') === 'cssSelector'"
+            v-if="
+              !hideMarkEl && (data.findBy || 'cssSelector') === 'cssSelector'
+            "
             :model-value="data.markEl"
             :model-value="data.markEl"
             :title="t('workflow.blocks.base.markElement.title')"
             :title="t('workflow.blocks.base.markElement.title')"
             @change="updateData({ markEl: $event })"
             @change="updateData({ markEl: $event })"
@@ -96,6 +98,10 @@ const props = defineProps({
     type: Boolean,
     type: Boolean,
     default: false,
     default: false,
   },
   },
+  hideMarkEl: {
+    type: Boolean,
+    default: false,
+  },
   hideSelector: {
   hideSelector: {
     type: Boolean,
     type: Boolean,
     default: false,
     default: false,

+ 5 - 1
src/components/newtab/workflow/editor/EditorUsedCredentials.vue

@@ -1,5 +1,9 @@
 <template>
 <template>
-  <ui-card padding="p-1" class="pointer-events-auto mr-4">
+  <ui-card
+    v-if="credentials.length > 0"
+    padding="p-1"
+    class="pointer-events-auto mr-4"
+  >
     <ui-popover v-tooltip="t('credential.use.title')" @show="checkCredentials">
     <ui-popover v-tooltip="t('credential.use.title')" @show="checkCredentials">
       <template #trigger>
       <template #trigger>
         <button class="p-2 hoverable transition">
         <button class="p-2 hoverable transition">

+ 93 - 0
src/content/blocksHandler/handlerCreateElement.js

@@ -0,0 +1,93 @@
+import { customAlphabet } from 'nanoid/non-secure';
+import handleSelector from '../handleSelector';
+import { automaRefDataStr } from '../utils';
+
+const nanoid = customAlphabet('1234567890abcdef', 5);
+const positions = {
+  after: 'beforeend',
+  before: 'afterbegin',
+  'next-sibling': 'afterend',
+  'prev-sibling': 'beforebegin',
+};
+
+function getAutomaScript(refData) {
+  const varName = `automa${nanoid()}`;
+
+  const str = `
+const ${varName} = ${JSON.stringify(refData)};
+${automaRefDataStr(varName)}
+function automaSetVariable(name, value) {
+  ${varName}.variables[name] = value;
+}
+function automaExecWorkflow(options = {}) {
+  window.dispatchEvent(new CustomEvent('automa:execute-workflow', { detail: options }));
+}
+  `;
+
+  return str;
+}
+function createNode(tag, attrs = {}, content = '') {
+  const element = document.createElement(tag);
+
+  Object.keys(attrs).forEach((attr) => {
+    element.setAttribute(attr, attrs[attr]);
+  });
+  element.innerHTML = content;
+
+  return element;
+}
+
+async function createElement(block) {
+  const targetElement = await handleSelector(block);
+  if (!targetElement) throw new Error('element-not-found');
+
+  const { data, id } = block;
+  const baseId = `automa-${id}`;
+
+  data.preloadScripts.forEach((item) => {
+    const scriptId = `${baseId}-script`;
+    const element = createNode(item.type, { id: scriptId }, item.script);
+
+    document.body.appendChild(element);
+  });
+
+  if (data.insertAt === 'replace') {
+    const elementWrapper = createNode(
+      data.elementWrapper,
+      { id: baseId },
+      data.html
+    );
+
+    targetElement.replaceWith(elementWrapper);
+  } else {
+    const tag = data.elementWrapper;
+    let htmlStr = `<${tag} id="${baseId}">${data.html}</${tag}/>`;
+
+    const form = ['input', 'select'];
+    if (form.includes(tag)) htmlStr = `<${tag} id="${baseId}" />`;
+
+    targetElement.insertAdjacentHTML(positions[data.insertAt], htmlStr);
+  }
+
+  if (data.css) {
+    const style = createNode('style', { id: `${baseId}-style` }, data.css);
+    document.body.appendChild(style);
+  }
+
+  if (data.javascript) {
+    const automaScript = `
+      (() => { ${getAutomaScript(block.refData)}\n${data.javascript} })()
+    `;
+    const script = createNode(
+      'script',
+      { id: `${baseId}-javascript` },
+      automaScript
+    );
+
+    document.body.appendChild(script);
+  }
+
+  return true;
+}
+
+export default createElement;

+ 2 - 0
src/content/commandPalette/App.vue

@@ -348,6 +348,8 @@ watch(
       state.retrieved = true;
       state.retrieved = true;
     } else if (!state.active) {
     } else if (!state.active) {
       clearParamsState();
       clearParamsState();
+      state.query = '';
+      state.selectedIndex = -1;
     }
     }
   }
   }
 );
 );

+ 2 - 0
src/lib/vRemixicon.js

@@ -43,6 +43,7 @@ import {
   riCheckLine,
   riCheckLine,
   riTimerLine,
   riTimerLine,
   riMagicLine,
   riMagicLine,
+  riHtml5Line,
   riToggleLine,
   riToggleLine,
   riFolderLine,
   riFolderLine,
   riGithubFill,
   riGithubFill,
@@ -168,6 +169,7 @@ export const icons = {
   riCheckLine,
   riCheckLine,
   riTimerLine,
   riTimerLine,
   riMagicLine,
   riMagicLine,
+  riHtml5Line,
   riToggleLine,
   riToggleLine,
   riFolderLine,
   riFolderLine,
   riGithubFill,
   riGithubFill,

+ 16 - 0
src/locales/en/blocks.json

@@ -213,6 +213,22 @@
         "name": "Hover element",
         "name": "Hover element",
         "description": "Hover over an element"
         "description": "Hover over an element"
       },
       },
+      "create-element": {
+        "name": "Create element",
+        "description": "Create an element and insert it into the page",
+        "edit": "Edit element",
+        "wrap": "Wrap the element inside",
+        "insertEl": {
+          "title": "Insert element",
+          "items": {
+            "before": "As first child",
+            "after": "As last child",
+            "next-sibling": "As next sibling",
+            "prev-sibling": "As previous sibling",
+            "replace": "Replace target element"
+          }
+        }
+      },
       "upload-file": {
       "upload-file": {
         "name": "Upload file",
         "name": "Upload file",
         "description": "Upload file into <input type=\"file\"> element",
         "description": "Upload file into <input type=\"file\"> element",

+ 2 - 1
src/newtab/pages/Workflows.vue

@@ -399,7 +399,7 @@ watch(
 
 
 onMounted(() => {
 onMounted(() => {
   const teams = [];
   const teams = [];
-  const unknownInputted = false;
+  let unknownInputted = false;
   Object.keys(teamWorkflowStore.workflows).forEach((id) => {
   Object.keys(teamWorkflowStore.workflows).forEach((id) => {
     const userTeam = userStore.user?.teams?.find(
     const userTeam = userStore.user?.teams?.find(
       (team) => team.id === id || team.id === +id
       (team) => team.id === id || team.id === +id
@@ -408,6 +408,7 @@ onMounted(() => {
     if (userTeam) {
     if (userTeam) {
       teams.push({ name: userTeam.name, id: userTeam.id });
       teams.push({ name: userTeam.name, id: userTeam.id });
     } else if (!unknownInputted) {
     } else if (!unknownInputted) {
+      unknownInputted = true;
       teams.unshift({ name: '(unknown)', id: '(unknown)' });
       teams.unshift({ name: '(unknown)', id: '(unknown)' });
     }
     }
   });
   });

+ 1 - 1
src/utils/handleFormElement.js

@@ -54,7 +54,7 @@ async function inputText({ data, element, isEditable }) {
   element?.focus();
   element?.focus();
   const elementKey = isEditable ? 'textContent' : 'value';
   const elementKey = isEditable ? 'textContent' : 'value';
 
 
-  if (data.delay > 0 && !document.hidden) {
+  if (data.delay > 0 && !document.hidden && !isEditable) {
     for (let index = 0; index < data.value.length; index += 1) {
     for (let index = 0; index < data.value.length; index += 1) {
       const currentChar = data.value[index];
       const currentChar = data.value[index];
       element[elementKey] += currentChar;
       element[elementKey] += currentChar;

+ 27 - 0
src/utils/shared.js

@@ -1184,6 +1184,33 @@ export const tasks = {
       variableName: '',
       variableName: '',
     },
     },
   },
   },
+  'create-element': {
+    name: 'Create element',
+    description: 'Create an element and insert it into the page',
+    icon: 'riHtml5Line',
+    editComponent: 'EditCreateElement',
+    component: 'BlockBasic',
+    category: 'interaction',
+    inputs: 1,
+    outputs: 1,
+    allowedInputs: true,
+    maxConnection: 1,
+    refDataKeys: ['html'],
+    data: {
+      disableBlock: false,
+      description: '',
+      javascript: '',
+      html: '',
+      css: '',
+      preloadScripts: [],
+      elementWrapper: 'div',
+      findBy: 'cssSelector',
+      insertAt: 'after',
+      waitForSelector: false,
+      waitSelectorTimeout: 5000,
+      selector: 'body',
+    },
+  },
 };
 };
 
 
 export const categories = {
 export const categories = {

+ 0 - 18
testing.html

@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-	<meta charset="utf-8">
-	<meta name="viewport" content="width=device-width, initial-scale=1">
-	<title></title>
-	<style type="text/css">
-		html {
-			height: 100vh;
-			width: 100vw;
-			background-color: #0f172a;
-		}
-	</style>
-</head>
-<body>
-	<p>hello</p>
-</body>
-</html>

+ 40 - 0
yarn.lock

@@ -937,6 +937,29 @@
     "@codemirror/view" "^6.0.0"
     "@codemirror/view" "^6.0.0"
     "@lezer/common" "^1.0.0"
     "@lezer/common" "^1.0.0"
 
 
+"@codemirror/lang-css@^6.0.0":
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/@codemirror/lang-css/-/lang-css-6.0.0.tgz#e66d087a4e52e334da4f5b3dfab47dbbdc5f6b15"
+  integrity sha512-jBqc+BTuwhNOTlrimFghLlSrN6iFuE44HULKWoR4qKYObhOIl9Lci1iYj6zMIte1XTQmZguNvjXMyr43LUKwSw==
+  dependencies:
+    "@codemirror/autocomplete" "^6.0.0"
+    "@codemirror/language" "^6.0.0"
+    "@codemirror/state" "^6.0.0"
+    "@lezer/css" "^1.0.0"
+
+"@codemirror/lang-html@^6.1.0":
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/@codemirror/lang-html/-/lang-html-6.1.0.tgz#5152a24c4febc265b4aad0bfcbc39bd805952d63"
+  integrity sha512-gA7NmJxqvnhwza05CvR7W/39Ap9r/4Vs9uiC0IeFYo1hSlJzc/8N6Evviz6vTW1x8SpHcRYyqKOf6rpl6LfWtg==
+  dependencies:
+    "@codemirror/autocomplete" "^6.0.0"
+    "@codemirror/lang-css" "^6.0.0"
+    "@codemirror/lang-javascript" "^6.0.0"
+    "@codemirror/language" "^6.0.0"
+    "@codemirror/state" "^6.0.0"
+    "@lezer/common" "^1.0.0"
+    "@lezer/html" "^1.0.0"
+
 "@codemirror/lang-javascript@^6.0.0":
 "@codemirror/lang-javascript@^6.0.0":
   version "6.0.1"
   version "6.0.1"
   resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-6.0.1.tgz#93237a61f9c67ca5d28f10bc064a8eeef5e03623"
   resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-6.0.1.tgz#93237a61f9c67ca5d28f10bc064a8eeef5e03623"
@@ -1193,6 +1216,14 @@
   resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.0.0.tgz#1c95ae53ec17706aa3cbcc88b52c23f22ed56096"
   resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.0.0.tgz#1c95ae53ec17706aa3cbcc88b52c23f22ed56096"
   integrity sha512-ohydQe+Hb+w4oMDvXzs8uuJd2NoA3D8YDcLiuDsLqH+yflDTPEpgCsWI3/6rH5C3BAedtH1/R51dxENldQceEA==
   integrity sha512-ohydQe+Hb+w4oMDvXzs8uuJd2NoA3D8YDcLiuDsLqH+yflDTPEpgCsWI3/6rH5C3BAedtH1/R51dxENldQceEA==
 
 
+"@lezer/css@^1.0.0":
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/@lezer/css/-/css-1.0.0.tgz#c473ea969238a36889533cb733b75539083a326d"
+  integrity sha512-616VqgDKumHmYIuxs3tnX1irEQmoDHgF/TlP4O5ICWwyHwLMErq+8iKVuzTkOdBqvYAVmObqThcDEAaaMJjAdg==
+  dependencies:
+    "@lezer/highlight" "^1.0.0"
+    "@lezer/lr" "^1.0.0"
+
 "@lezer/highlight@^1.0.0":
 "@lezer/highlight@^1.0.0":
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.0.0.tgz#1dc82300f5d39fbd67ae1194b5519b4c381878d3"
   resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.0.0.tgz#1dc82300f5d39fbd67ae1194b5519b4c381878d3"
@@ -1200,6 +1231,15 @@
   dependencies:
   dependencies:
     "@lezer/common" "^1.0.0"
     "@lezer/common" "^1.0.0"
 
 
+"@lezer/html@^1.0.0":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@lezer/html/-/html-1.0.1.tgz#5d62b98cdd37e50394e1b7097c86d8ce3ef128b8"
+  integrity sha512-sC00zEt3GBh3vVO6QaGX4YZCl41S9dHWN/WGBsDixy9G+sqOC7gsa4cxA/fmRVAiBvhqYkJk+5Ul4oul92CPVw==
+  dependencies:
+    "@lezer/common" "^1.0.0"
+    "@lezer/highlight" "^1.0.0"
+    "@lezer/lr" "^1.0.0"
+
 "@lezer/javascript@^1.0.0":
 "@lezer/javascript@^1.0.0":
   version "1.0.1"
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-1.0.1.tgz#4ae85aebac17e56c97b9922f4cdf255332d8b7bb"
   resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-1.0.1.tgz#4ae85aebac17e56c97b9922f4cdf255332d8b7bb"

Some files were not shown because too many files changed in this diff