Path: blob/main/src/command/dev-call/build-artifacts/cmd.ts
3587 views
/*1* cmd.ts2*3* Copyright (C) 2021-2022 Posit Software, PBC4*/56import { Command } from "cliffy/command/mod.ts";78import {9ESBuildAnalysis,10esbuildAnalyze,11esbuildCompile,12} from "../../../core/esbuild.ts";13import { buildIntelligenceResources } from "../../../core/schema/build-schema-file.ts";14import { formatResourcePath, resourcePath } from "../../../core/resources.ts";15import { simple } from "acorn/walk";16import { Parser } from "acorn/acorn";17import classFields from "acorn-class-fields";18import { initYamlIntelligenceResourcesFromFilesystem } from "../../../core/schema/utils.ts";1920// initialize language handlers21import "../../../core/handlers/handlers.ts";22import { join } from "../../../deno_ral/path.ts";2324function ensureAllowableIDESyntax(src: string, filename: string) {25const ast = Parser.extend(classFields).parse(src, {26ecmaVersion: "2020",27sourceType: "module",28});29let failed = false;30simple(ast, {31// deno-lint-ignore no-explicit-any32ChainExpression(_node: any) {33console.error(34`Failure: Chain expression \`?.\` not allowed in ${filename}`,35);36failed = true;37},38// deno-lint-ignore no-explicit-any39LogicalExpression(node: any) {40if (node.operator === "??") {41console.error(42`Failure: Nullish coalescing operator \`??\` not allows in ${filename}`,43);44failed = true;45}46},47});48if (failed) {49throw new Error("Found syntax that is not allowed");50}51}5253async function buildYAMLJS() {54// convert tree-sitter-yaml to a JSON object that can be imported directly.55// In principle this never changes so running it every time is overkill, but this56// way we document the generation of the JSON object.57//58// inexplicably, using TextEncoder inside a web worker on QtWebEngine freezes59// the entire thread. That means we can't use base64 strings to encode the wasm60// values. So we will encode them as plain js numbers. facepalm61const treeSitterYamlJson = {62"data": Array.from(Deno.readFileSync(63resourcePath("editor/tools/yaml/tree-sitter-yaml.wasm"),64)),65};66Deno.writeTextFileSync(67resourcePath("editor/tools/yaml/tree-sitter-yaml.json"),68JSON.stringify(treeSitterYamlJson),69);7071const esbuild = async (72cwd: string,73filename: string,74outputType: "esm" | "iife" | "cjs" = "iife",75checkIde = true,76) => {77const result = (await esbuildCompile(78"",79cwd,80[filename],81outputType,82))!;83if (checkIde) {84ensureAllowableIDESyntax(result, filename);85}86return result;87};8889Deno.writeTextFileSync(90resourcePath("editor/tools/yaml/yaml-intelligence.js"),91await esbuild(92resourcePath("../core/lib/yaml-intelligence"),93"ide-main.ts",94"esm",95),96);9798Deno.writeTextFileSync(99resourcePath("editor/tools/yaml/yaml.js"),100await esbuild(101resourcePath("editor/tools/yaml"),102"automation.js",103),104);105106const webWorkerSrc = await esbuild(107resourcePath("../core/lib/yaml-intelligence"),108"web-worker.ts",109);110const vsCodeSrc = await esbuild(111resourcePath("../core/lib/yaml-intelligence"),112"vs-code.ts",113"esm",114false,115);116117const treeSitter = Deno.readTextFileSync(118resourcePath("editor/tools/yaml/tree-sitter.js"),119);120ensureAllowableIDESyntax(treeSitter, "tree-sitter.js");121122Deno.writeTextFileSync(123resourcePath("editor/tools/vs-code.mjs"),124[treeSitter, vsCodeSrc].join(""),125);126127Deno.writeTextFileSync(128resourcePath("editor/tools/yaml/web-worker.js"),129[treeSitter, webWorkerSrc].join(""),130);131}132133async function buildEsbuildAnalysisCache() {134// build the necessary esbuild analysis cache135const inputFiles = [136"quarto.js",137];138const analysisCache: Record<string, ESBuildAnalysis> = {};139for (const file of inputFiles) {140analysisCache[file] = await esbuildAnalyze(141formatResourcePath("html", file),142resourcePath(join("formats", "html")),143);144}145Deno.writeTextFileSync(146formatResourcePath("html", "esbuild-analysis-cache.json"),147JSON.stringify(analysisCache, null, 2),148);149}150151export async function buildAssets() {152// this has to come first because buildYAMLJS depends on it.153await buildIntelligenceResources();154await buildYAMLJS();155await buildEsbuildAnalysisCache();156}157158export const buildJsCommand = new Command()159.name("build-artifacts")160.hidden()161.description(162"Builds all the javascript assets necessary for IDE support.\n\n",163)164.action(async () => {165await initYamlIntelligenceResourcesFromFilesystem();166await buildAssets();167});168169170