wip: compat layer

This commit is contained in:
Jordan Pittman 2024-10-12 18:52:52 -04:00
parent ff0a5e3f7b
commit eeb38e7399
13 changed files with 565 additions and 0 deletions

View file

@ -0,0 +1,14 @@
import * as net from 'node:net'
import * as rpc from 'vscode-jsonrpc/node'
let client = net.connect(12345)
// Use stdin and stdout for communication:
let connection = rpc.createMessageConnection(client, client)
connection.onNotification('loaded', () => console.log('server loaded'))
connection.onNotification('ping', () => console.log('ping'))
connection.onNotification('@/plugins/loaded', () => console.log('plugins loaded'))
connection.listen()
connection.sendRequest('@/plugins/load', 'foo')

View file

@ -0,0 +1,127 @@
export type PluginFn = (api: PluginAPI) => void
export type PluginWithConfig = { handler: PluginFn }
export type PluginWithOptions<T> = {
(options?: T): PluginWithConfig
__isOptionsFunction: true
}
export type Plugin = PluginFn | PluginWithConfig | PluginWithOptions<any>
export type CssInJs = { [key: string]: string | CssInJs | CssInJs[] }
export type NamedUtilityValue = {
kind: 'named'
/**
* bg-red-500
* ^^^^^^^
*
* w-1/2
* ^
*/
value: string
/**
* w-1/2
* ^^^
*/
fraction: string | null
}
export type PluginAPI = {
addBase(base: CssInJs): void
addVariant(name: string, variant: string | string[] | CssInJs): void
addUtilities(
utilities: Record<string, CssInJs | CssInJs[]> | Record<string, CssInJs | CssInJs[]>[],
options?: {},
): void
matchUtilities(
utilities: Record<
string,
(value: string, extra: { modifier: string | null }) => CssInJs | CssInJs[]
>,
options?: Partial<{
type: string | string[]
supportsNegativeValues: boolean
values: Record<string, string> & {
__BARE_VALUE__?: (value: NamedUtilityValue) => string | undefined
}
modifiers: 'any' | Record<string, string>
}>,
): void
// addComponents(utilities: Record<string, CssInJs> | Record<string, CssInJs>[], options?: {}): void
// matchComponents(
// utilities: Record<string, (value: string, extra: { modifier: string | null }) => CssInJs>,
// options?: Partial<{
// type: string | string[]
// supportsNegativeValues: boolean
// values: Record<string, string> & {
// __BARE_VALUE__?: (value: NamedUtilityValue) => string | undefined
// }
// modifiers: 'any' | Record<string, string>
// }>,
// ): void
// theme(path: string, defaultValue?: any): any
// prefix(className: string): string
}
import * as rpc from 'vscode-jsonrpc/node'
export function buildPluginController(server: rpc.MessageConnection) {
let utilityMap = new Map<
string,
(value: string, extra: { modifier: string | null }) => CssInJs | CssInJs[]
>()
let api = buildPluginApi(server, utilityMap)
return {
api,
matchUtility(id: string, value: string, modifier: string | null) {
let fn = utilityMap.get(id)
if (!fn) return
return fn(value, { modifier })
},
}
}
function buildPluginApi(
server: rpc.MessageConnection,
utilityMap: Map<
string,
(value: string, extra: { modifier: string | null }) => CssInJs | CssInJs[]
>,
): PluginAPI {
return {
addBase(base) {
server.sendNotification('@/plugin/add-base', { ast: base })
},
addVariant(name, variant) {
server.sendNotification('@/plugin/add-variant', { name, format: variant })
},
addUtilities(utilities, options) {
server.sendNotification('@/plugin/add-utilities', { ast: utilities, options })
},
matchUtilities(utilities, options) {
let namesToIds: Record<string, string> = {}
for (let [name, fn] of Object.entries(utilities)) {
let id = Math.random().toString(36).slice(2)
namesToIds[name] = id
utilityMap.set(id, fn)
}
server.sendNotification('@/plugin/match-utility', {
utilities: namesToIds,
})
},
}
}

View file

@ -0,0 +1,27 @@
import type { PluginAPI } from './plugin-api'
module.exports = function ({ addBase, addVariant, addUtilities, matchUtilities }: PluginAPI) {
addBase({
div: {
transform: 'skewY(-10deg)',
},
})
addVariant('hover', ':hover')
addVariant('marker', ['::marker', '* ::marker'])
addUtilities({
'.skew-10deg': {
transform: 'skewY(-10deg)',
},
})
matchUtilities(
{ skew: (value) => ({ transform: `skewY(${value})` }) },
{
values: {
f10: '10deg',
},
},
)
}

View file

@ -0,0 +1,33 @@
import * as net from 'node:net'
import * as rpc from 'vscode-jsonrpc/node'
import { buildPluginController, PluginFn } from './plugin-api'
let socket = await new Promise<net.Socket>((resolve) => {
net.createServer(resolve).listen(12345)
})
let server = rpc.createMessageConnection(socket, socket)
let controller = buildPluginController(server)
async function loadPlugin(path: string): Promise<PluginFn> {
return import(path).then((m) => m.default ?? m)
}
server.onRequest('@/plugins/load', async ({ plugins: paths }) => {
console.log('Loading…')
let plugins: PluginFn[] = await Promise.all(paths.map(loadPlugin))
for (let plugin of plugins) {
plugin(controller.api)
}
console.log('Loaded…')
})
server.onRequest('@/plugins/match-utility', async ({ id, value, modifier }) => {
let ast = controller.matchUtility(id, value, modifier)
return { ast }
})
server.listen()
server.sendNotification('loaded')