Merge branch 'master' into convert-client-builder-store

This commit is contained in:
Adria Navarro 2025-02-13 13:01:01 +01:00 committed by GitHub
commit cd41bb8a7f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 197 additions and 141 deletions

View File

@ -53,7 +53,7 @@
"@budibase/shared-core": "*", "@budibase/shared-core": "*",
"@budibase/string-templates": "*", "@budibase/string-templates": "*",
"@budibase/types": "*", "@budibase/types": "*",
"@codemirror/autocomplete": "^6.7.1", "@codemirror/autocomplete": "6.9.0",
"@codemirror/commands": "^6.2.4", "@codemirror/commands": "^6.2.4",
"@codemirror/lang-javascript": "^6.1.8", "@codemirror/lang-javascript": "^6.1.8",
"@codemirror/language": "^6.6.0", "@codemirror/language": "^6.6.0",

View File

@ -45,10 +45,11 @@
import { EditorModes } from "./" import { EditorModes } from "./"
import { themeStore } from "@/stores/portal" import { themeStore } from "@/stores/portal"
import type { EditorMode } from "@budibase/types" import type { EditorMode } from "@budibase/types"
import type { BindingCompletion } from "@/types"
export let label: string | undefined = undefined export let label: string | undefined = undefined
// TODO: work out what best type fits this // TODO: work out what best type fits this
export let completions: any[] = [] export let completions: BindingCompletion[] = []
export let mode: EditorMode = EditorModes.Handlebars export let mode: EditorMode = EditorModes.Handlebars
export let value: string | null = "" export let value: string | null = ""
export let placeholder: string | null = null export let placeholder: string | null = null

View File

@ -1,13 +1,10 @@
import { getManifest } from "@budibase/string-templates" import { getManifest } from "@budibase/string-templates"
import sanitizeHtml from "sanitize-html" import sanitizeHtml from "sanitize-html"
import { groupBy } from "lodash" import { groupBy } from "lodash"
import { import { EditorModesMap, Helper, Snippet } from "@budibase/types"
BindingCompletion,
EditorModesMap,
Helper,
Snippet,
} from "@budibase/types"
import { CompletionContext } from "@codemirror/autocomplete" import { CompletionContext } from "@codemirror/autocomplete"
import { EditorView } from "@codemirror/view"
import { BindingCompletion, BindingCompletionOption } from "@/types"
export const EditorModes: EditorModesMap = { export const EditorModes: EditorModesMap = {
JS: { JS: {
@ -25,15 +22,7 @@ export const EditorModes: EditorModesMap = {
}, },
} }
export const SECTIONS = { const buildHelperInfoNode = (helper: Helper) => {
HB_HELPER: {
name: "Helper",
type: "helper",
icon: "Code",
},
}
export const buildHelperInfoNode = (completion: any, helper: Helper) => {
const ele = document.createElement("div") const ele = document.createElement("div")
ele.classList.add("info-bubble") ele.classList.add("info-bubble")
@ -65,7 +54,7 @@ const toSpectrumIcon = (name: string) => {
</svg>` </svg>`
} }
export const buildSectionHeader = ( const buildSectionHeader = (
type: string, type: string,
sectionName: string, sectionName: string,
icon: string, icon: string,
@ -84,30 +73,27 @@ export const buildSectionHeader = (
} }
} }
export const helpersToCompletion = ( const helpersToCompletion = (
helpers: Record<string, Helper>, helpers: Record<string, Helper>,
mode: { name: "javascript" | "handlebars" } mode: { name: "javascript" | "handlebars" }
) => { ): BindingCompletionOption[] => {
const { type, name: sectionName, icon } = SECTIONS.HB_HELPER const helperSection = buildSectionHeader("helper", "Helpers", "Code", 99)
const helperSection = buildSectionHeader(type, sectionName, icon, 99)
return Object.keys(helpers).flatMap(helperName => { return Object.keys(helpers).flatMap(helperName => {
let helper = helpers[helperName] const helper = helpers[helperName]
return { return {
label: helperName, label: helperName,
info: (completion: BindingCompletion) => { info: () => buildHelperInfoNode(helper),
return buildHelperInfoNode(completion, helper)
},
type: "helper", type: "helper",
section: helperSection, section: helperSection,
detail: "Function", detail: "Function",
apply: ( apply: (
view: any, view: EditorView,
completion: BindingCompletion, _completion: BindingCompletionOption,
from: number, from: number,
to: number to: number
) => { ) => {
insertBinding(view, from, to, helperName, mode) insertBinding(view, from, to, helperName, mode, AutocompleteType.HELPER)
}, },
} }
}) })
@ -115,7 +101,7 @@ export const helpersToCompletion = (
export const getHelperCompletions = (mode: { export const getHelperCompletions = (mode: {
name: "javascript" | "handlebars" name: "javascript" | "handlebars"
}) => { }): BindingCompletionOption[] => {
// TODO: manifest needs to be properly typed // TODO: manifest needs to be properly typed
const manifest: any = getManifest() const manifest: any = getManifest()
return Object.keys(manifest).flatMap(key => { return Object.keys(manifest).flatMap(key => {
@ -123,49 +109,33 @@ export const getHelperCompletions = (mode: {
}) })
} }
export const snippetAutoComplete = (snippets: Snippet[]) => { export const snippetAutoComplete = (snippets: Snippet[]): BindingCompletion => {
return function myCompletions(context: CompletionContext) { return setAutocomplete(
if (!snippets?.length) { snippets.map(snippet => ({
return null section: buildSectionHeader("snippets", "Snippets", "Code", 100),
} label: `snippets.${snippet.name}`,
const word = context.matchBefore(/\w*/) displayLabel: snippet.name,
if (!word || (word.from == word.to && !context.explicit)) { }))
return null )
}
return {
from: word.from,
options: snippets.map(snippet => ({
label: `snippets.${snippet.name}`,
type: "text",
simple: true,
apply: (
view: any,
completion: BindingCompletion,
from: number,
to: number
) => {
insertSnippet(view, from, to, completion.label)
},
})),
}
}
} }
const bindingFilter = (options: BindingCompletion[], query: string) => { const bindingFilter = (options: BindingCompletionOption[], query: string) => {
return options.filter(completion => { return options.filter(completion => {
const section_parsed = completion.section.name.toLowerCase() const section_parsed = completion.section?.toString().toLowerCase()
const label_parsed = completion.label.toLowerCase() const label_parsed = completion.label.toLowerCase()
const query_parsed = query.toLowerCase() const query_parsed = query.toLowerCase()
return ( return (
section_parsed.includes(query_parsed) || section_parsed?.includes(query_parsed) ||
label_parsed.includes(query_parsed) label_parsed.includes(query_parsed)
) )
}) })
} }
export const hbAutocomplete = (baseCompletions: BindingCompletion[]) => { export const hbAutocomplete = (
async function coreCompletion(context: CompletionContext) { baseCompletions: BindingCompletionOption[]
): BindingCompletion => {
function coreCompletion(context: CompletionContext) {
let bindingStart = context.matchBefore(EditorModes.Handlebars.match) let bindingStart = context.matchBefore(EditorModes.Handlebars.match)
let options = baseCompletions || [] let options = baseCompletions || []
@ -191,9 +161,15 @@ export const hbAutocomplete = (baseCompletions: BindingCompletion[]) => {
return coreCompletion return coreCompletion
} }
export const jsAutocomplete = (baseCompletions: BindingCompletion[]) => { function wrappedAutocompleteMatch(context: CompletionContext) {
async function coreCompletion(context: CompletionContext) { return context.matchBefore(/\$\("[\s\w]*/)
let jsBinding = context.matchBefore(/\$\("[\s\w]*/) }
export const jsAutocomplete = (
baseCompletions: BindingCompletionOption[]
): BindingCompletion => {
function coreCompletion(context: CompletionContext) {
let jsBinding = wrappedAutocompleteMatch(context)
let options = baseCompletions || [] let options = baseCompletions || []
if (jsBinding) { if (jsBinding) {
@ -217,10 +193,42 @@ export const jsAutocomplete = (baseCompletions: BindingCompletion[]) => {
return coreCompletion return coreCompletion
} }
export const buildBindingInfoNode = ( export const jsHelperAutocomplete = (
completion: BindingCompletion, baseCompletions: BindingCompletionOption[]
binding: any ): BindingCompletion => {
) => { return setAutocomplete(
baseCompletions.map(helper => ({
...helper,
displayLabel: helper.label,
label: `helpers.${helper.label}()`,
}))
)
}
function setAutocomplete(
options: BindingCompletionOption[]
): BindingCompletion {
return function (context: CompletionContext) {
if (wrappedAutocompleteMatch(context)) {
return null
}
const word = context.matchBefore(/\b\w*(\.\w*)?/)
if (!word || (word.from == word.to && !context.explicit)) {
return null
}
return {
from: word.from,
options,
}
}
}
const buildBindingInfoNode = (binding: {
valueHTML: string
value: string | null
}) => {
if (!binding.valueHTML || binding.value == null) { if (!binding.valueHTML || binding.value == null) {
return null return null
} }
@ -278,18 +286,28 @@ export function jsInsert(
return parsedInsert return parsedInsert
} }
const enum AutocompleteType {
BINDING,
HELPER,
TEXT,
}
// Autocomplete apply behaviour // Autocomplete apply behaviour
export const insertBinding = ( const insertBinding = (
view: any, view: EditorView,
from: number, from: number,
to: number, to: number,
text: string, text: string,
mode: { name: "javascript" | "handlebars" } mode: { name: "javascript" | "handlebars" },
type: AutocompleteType
) => { ) => {
let parsedInsert let parsedInsert
if (mode.name == "javascript") { if (mode.name == "javascript") {
parsedInsert = jsInsert(view.state.doc?.toString(), from, to, text) parsedInsert = jsInsert(view.state.doc?.toString(), from, to, text, {
helper: type === AutocompleteType.HELPER,
disableWrapping: type === AutocompleteType.TEXT,
})
} else if (mode.name == "handlebars") { } else if (mode.name == "handlebars") {
parsedInsert = hbInsert(view.state.doc?.toString(), from, to, text) parsedInsert = hbInsert(view.state.doc?.toString(), from, to, text)
} else { } else {
@ -319,30 +337,11 @@ export const insertBinding = (
}) })
} }
export const insertSnippet = (
view: any,
from: number,
to: number,
text: string
) => {
let cursorPos = from + text.length
view.dispatch({
changes: {
from,
to,
insert: text,
},
selection: {
anchor: cursorPos,
},
})
}
// TODO: typing in this function isn't great // TODO: typing in this function isn't great
export const bindingsToCompletions = ( export const bindingsToCompletions = (
bindings: any, bindings: any,
mode: { name: "javascript" | "handlebars" } mode: { name: "javascript" | "handlebars" }
) => { ): BindingCompletionOption[] => {
const bindingByCategory = groupBy(bindings, "category") const bindingByCategory = groupBy(bindings, "category")
const categoryMeta = bindings?.reduce((acc: any, ele: any) => { const categoryMeta = bindings?.reduce((acc: any, ele: any) => {
acc[ele.category] = acc[ele.category] || {} acc[ele.category] = acc[ele.category] || {}
@ -356,46 +355,54 @@ export const bindingsToCompletions = (
return acc return acc
}, {}) }, {})
const completions = Object.keys(bindingByCategory).reduce( const completions = Object.keys(bindingByCategory).reduce<
(comps: any, catKey: string) => { BindingCompletionOption[]
const { icon, rank } = categoryMeta[catKey] || {} >((comps, catKey) => {
const { icon, rank } = categoryMeta[catKey] || {}
const bindingSectionHeader = buildSectionHeader( const bindingSectionHeader = buildSectionHeader(
// @ts-ignore something wrong with this - logically this should be dictionary // @ts-ignore something wrong with this - logically this should be dictionary
bindingByCategory.type, bindingByCategory.type,
catKey, catKey,
icon || "", icon || "",
typeof rank == "number" ? rank : 1 typeof rank == "number" ? rank : 1
) )
return [ comps.push(
...comps, ...bindingByCategory[catKey].reduce<BindingCompletionOption[]>(
...bindingByCategory[catKey].reduce((acc, binding) => { (acc, binding) => {
let displayType = binding.fieldSchema?.type || binding.display?.type let displayType = binding.fieldSchema?.type || binding.display?.type
acc.push({ acc.push({
label: label:
binding.display?.name || binding.readableBinding || "NO NAME", binding.display?.name || binding.readableBinding || "NO NAME",
info: (completion: BindingCompletion) => { info: () => buildBindingInfoNode(binding),
return buildBindingInfoNode(completion, binding)
},
type: "binding", type: "binding",
detail: displayType, detail: displayType,
section: bindingSectionHeader, section: bindingSectionHeader,
apply: ( apply: (
view: any, view: EditorView,
completion: BindingCompletion, _completion: BindingCompletionOption,
from: number, from: number,
to: number to: number
) => { ) => {
insertBinding(view, from, to, binding.readableBinding, mode) insertBinding(
view,
from,
to,
binding.readableBinding,
mode,
AutocompleteType.BINDING
)
}, },
}) })
return acc return acc
}, []), },
] []
}, )
[] )
)
return comps
}, [])
return completions return completions
} }

View File

@ -23,6 +23,7 @@
snippetAutoComplete, snippetAutoComplete,
EditorModes, EditorModes,
bindingsToCompletions, bindingsToCompletions,
jsHelperAutocomplete,
} from "../CodeEditor" } from "../CodeEditor"
import BindingSidePanel from "./BindingSidePanel.svelte" import BindingSidePanel from "./BindingSidePanel.svelte"
import EvaluationSidePanel from "./EvaluationSidePanel.svelte" import EvaluationSidePanel from "./EvaluationSidePanel.svelte"
@ -34,7 +35,6 @@
import { BindingMode, SidePanel } from "@budibase/types" import { BindingMode, SidePanel } from "@budibase/types"
import type { import type {
EnrichedBinding, EnrichedBinding,
BindingCompletion,
Snippet, Snippet,
Helper, Helper,
CaretPositionFn, CaretPositionFn,
@ -42,7 +42,7 @@
JSONValue, JSONValue,
} from "@budibase/types" } from "@budibase/types"
import type { Log } from "@budibase/string-templates" import type { Log } from "@budibase/string-templates"
import type { CompletionContext } from "@codemirror/autocomplete" import type { BindingCompletion, BindingCompletionOption } from "@/types"
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
@ -91,7 +91,10 @@
$: bindingCompletions = bindingsToCompletions(enrichedBindings, editorMode) $: bindingCompletions = bindingsToCompletions(enrichedBindings, editorMode)
$: bindingHelpers = new BindingHelpers(getCaretPosition, insertAtPos) $: bindingHelpers = new BindingHelpers(getCaretPosition, insertAtPos)
$: hbsCompletions = getHBSCompletions(bindingCompletions) $: hbsCompletions = getHBSCompletions(bindingCompletions)
$: jsCompletions = getJSCompletions(bindingCompletions, snippets, useSnippets) $: jsCompletions = getJSCompletions(bindingCompletions, snippets, {
useHelpers: allowHelpers,
useSnippets,
})
$: { $: {
// Ensure a valid side panel option is always selected // Ensure a valid side panel option is always selected
if (sidePanel && !sidePanelOptions.includes(sidePanel)) { if (sidePanel && !sidePanelOptions.includes(sidePanel)) {
@ -99,7 +102,7 @@
} }
} }
const getHBSCompletions = (bindingCompletions: BindingCompletion[]) => { const getHBSCompletions = (bindingCompletions: BindingCompletionOption[]) => {
return [ return [
hbAutocomplete([ hbAutocomplete([
...bindingCompletions, ...bindingCompletions,
@ -109,17 +112,23 @@
} }
const getJSCompletions = ( const getJSCompletions = (
bindingCompletions: BindingCompletion[], bindingCompletions: BindingCompletionOption[],
snippets: Snippet[] | null, snippets: Snippet[] | null,
useSnippets?: boolean config: {
useHelpers: boolean
useSnippets: boolean
}
) => { ) => {
const completions: ((_: CompletionContext) => any)[] = [ const completions: BindingCompletion[] = []
jsAutocomplete([ if (bindingCompletions.length) {
...bindingCompletions, completions.push(jsAutocomplete([...bindingCompletions]))
...getHelperCompletions(EditorModes.JS), }
]), if (config.useHelpers) {
] completions.push(
if (useSnippets && snippets) { jsHelperAutocomplete([...getHelperCompletions(EditorModes.JS)])
)
}
if (config.useSnippets && snippets) {
completions.push(snippetAutoComplete(snippets)) completions.push(snippetAutoComplete(snippets))
} }
return completions return completions
@ -381,7 +390,7 @@
autofocus={autofocusEditor} autofocus={autofocusEditor}
placeholder={placeholder || placeholder={placeholder ||
"Add bindings by typing $ or use the menu on the right"} "Add bindings by typing $ or use the menu on the right"}
jsBindingWrapping jsBindingWrapping={bindingCompletions.length > 0}
/> />
{/key} {/key}
{/if} {/if}

View File

@ -118,6 +118,7 @@
allowHBS={false} allowHBS={false}
allowJS allowJS
allowSnippets={false} allowSnippets={false}
allowHelpers={false}
showTabBar={false} showTabBar={false}
placeholder="return function(input) &#10100; ... &#10101;" placeholder="return function(input) &#10100; ... &#10101;"
value={code} value={code}

View File

@ -0,0 +1,8 @@
import { CompletionContext, Completion } from "@codemirror/autocomplete"
export type BindingCompletion = (context: CompletionContext) => {
from: number
options: Completion[]
} | null
export type BindingCompletionOption = Completion

View File

@ -0,0 +1 @@
export * from "./bindings"

View File

@ -1,10 +1,3 @@
export interface BindingCompletion {
section: {
name: string
}
label: string
}
export interface EnrichedBinding { export interface EnrichedBinding {
runtimeBinding: string runtimeBinding: string
readableBinding: string readableBinding: string

View File

@ -2834,16 +2834,26 @@
dependencies: dependencies:
"@bull-board/api" "5.10.2" "@bull-board/api" "5.10.2"
"@codemirror/autocomplete@^6.0.0", "@codemirror/autocomplete@^6.7.1": "@codemirror/autocomplete@6.9.0":
version "6.7.1" version "6.9.0"
resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.7.1.tgz#3364799b78dff70fb8f81615536c52ea53ce40b2" resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.9.0.tgz#1a1e63122288b8f8e1e9d7aff2eb39a83e04d8a9"
integrity sha512-hSxf9S0uB+GV+gBsjY1FZNo53e1FFdzPceRfCfD1gWOnV6o21GfB5J5Wg9G/4h76XZMPrF0A6OCK/Rz5+V1egg== integrity sha512-Fbwm0V/Wn3BkEJZRhr0hi5BhCo5a7eBL6LYaliPjOSwCyfOpnjXY59HruSxOUNV+1OYer0Tgx1zRNQttjXyDog==
dependencies: dependencies:
"@codemirror/language" "^6.0.0" "@codemirror/language" "^6.0.0"
"@codemirror/state" "^6.0.0" "@codemirror/state" "^6.0.0"
"@codemirror/view" "^6.6.0" "@codemirror/view" "^6.6.0"
"@lezer/common" "^1.0.0" "@lezer/common" "^1.0.0"
"@codemirror/autocomplete@^6.0.0":
version "6.18.4"
resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.18.4.tgz#4394f55d6771727179f2e28a871ef46bbbeb11b1"
integrity sha512-sFAphGQIqyQZfP2ZBsSHV7xQvo9Py0rV0dW7W3IMRdS+zDuNb2l3no78CvUaWKGfzFjI4FTrLdUSj86IGb2hRA==
dependencies:
"@codemirror/language" "^6.0.0"
"@codemirror/state" "^6.0.0"
"@codemirror/view" "^6.17.0"
"@lezer/common" "^1.0.0"
"@codemirror/commands@^6.2.4": "@codemirror/commands@^6.2.4":
version "6.2.4" version "6.2.4"
resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.2.4.tgz#b8a0e5ce72448c092ba4c4b1d902e6f183948aec" resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.2.4.tgz#b8a0e5ce72448c092ba4c4b1d902e6f183948aec"
@ -2893,6 +2903,13 @@
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.2.0.tgz#a0fb08403ced8c2a68d1d0acee926bd20be922f2" resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.2.0.tgz#a0fb08403ced8c2a68d1d0acee926bd20be922f2"
integrity sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA== integrity sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA==
"@codemirror/state@^6.5.0":
version "6.5.2"
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6"
integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==
dependencies:
"@marijn/find-cluster-break" "^1.0.0"
"@codemirror/theme-one-dark@^6.1.2": "@codemirror/theme-one-dark@^6.1.2":
version "6.1.2" version "6.1.2"
resolved "https://registry.yarnpkg.com/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz#fcef9f9cfc17a07836cb7da17c9f6d7231064df8" resolved "https://registry.yarnpkg.com/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz#fcef9f9cfc17a07836cb7da17c9f6d7231064df8"
@ -2912,6 +2929,15 @@
style-mod "^4.0.0" style-mod "^4.0.0"
w3c-keyname "^2.2.4" w3c-keyname "^2.2.4"
"@codemirror/view@^6.17.0":
version "6.36.2"
resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.36.2.tgz#aeb644e161440734ac5a153bf6e5b4a4355047be"
integrity sha512-DZ6ONbs8qdJK0fdN7AB82CgI6tYXf4HWk1wSVa0+9bhVznCuuvhQtX8bFBoy3dv8rZSQqUd8GvhVAcielcidrA==
dependencies:
"@codemirror/state" "^6.5.0"
style-mod "^4.1.0"
w3c-keyname "^2.2.4"
"@colors/colors@1.6.0", "@colors/colors@^1.6.0": "@colors/colors@1.6.0", "@colors/colors@^1.6.0":
version "1.6.0" version "1.6.0"
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0"
@ -4133,6 +4159,11 @@
semver "^7.3.5" semver "^7.3.5"
tar "^6.1.11" tar "^6.1.11"
"@marijn/find-cluster-break@^1.0.0":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz#775374306116d51c0c500b8c4face0f9a04752d8"
integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==
"@mongodb-js/saslprep@^1.1.5": "@mongodb-js/saslprep@^1.1.5":
version "1.1.7" version "1.1.7"
resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.1.7.tgz#d1700facfd6916c50c2c88fd6d48d363a56c702f" resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.1.7.tgz#d1700facfd6916c50c2c88fd6d48d363a56c702f"
@ -19961,6 +19992,11 @@ style-mod@^4.0.0:
resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.0.3.tgz#136c4abc905f82a866a18b39df4dc08ec762b1ad" resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.0.3.tgz#136c4abc905f82a866a18b39df4dc08ec762b1ad"
integrity sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw== integrity sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw==
style-mod@^4.1.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.1.2.tgz#ca238a1ad4786520f7515a8539d5a63691d7bf67"
integrity sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==
stylus-lookup@^3.0.1: stylus-lookup@^3.0.1:
version "3.0.2" version "3.0.2"
resolved "https://registry.yarnpkg.com/stylus-lookup/-/stylus-lookup-3.0.2.tgz#c9eca3ff799691020f30b382260a67355fefdddd" resolved "https://registry.yarnpkg.com/stylus-lookup/-/stylus-lookup-3.0.2.tgz#c9eca3ff799691020f30b382260a67355fefdddd"