diff --git a/kastro/compiler/jsx-runtime.js b/kastro/compiler/jsx-runtime.js index 61f24b6..0a21bb9 100644 --- a/kastro/compiler/jsx-runtime.js +++ b/kastro/compiler/jsx-runtime.js @@ -1,5 +1,5 @@ import { KapalıTag, tagYaz } from "../../util/html"; -import { LangCode } from "../crate"; +import { LangCode } from "../../util/i18n"; import { getGlobals } from "./pageGlobals"; /** @const {string} */ diff --git a/kastro/compiler/loader/workerLoader.js b/kastro/compiler/loader/workerLoader.js new file mode 100644 index 0000000..e69de29 diff --git a/kastro/compiler/pageGlobals.js b/kastro/compiler/pageGlobals.js index a0beb3b..b5a2e89 100644 --- a/kastro/compiler/pageGlobals.js +++ b/kastro/compiler/pageGlobals.js @@ -1,3 +1,5 @@ +import { filterGlobalProps } from "../props"; + let Globals = {}; /** @@ -5,22 +7,15 @@ let Globals = {}; * @param {!Object} newGlobals - An object containing key-value pairs to set as globals. * @return {!Object} The new globals object. */ -const initGlobals = (globalsData) => { - const filteredData = {}; - for (const key in globalsData) { - if (key.charCodeAt(0) < 91) - filteredData[key] = globalsData[key]; - } - return Globals = new Proxy(filteredData, { - set(target, key, value) { - if (key.charCodeAt(0) > 90) - throw new Error(`Global key "${key}" must start with a capital letter.`); +const initGlobals = (globalsData) => Globals = new Proxy(filterGlobalProps(globalsData), { + set(target, key, value) { + if (key.charCodeAt(0) > 90) + throw new Error(`Global key "${key}" must start with a capital letter.`); - target[key] = value; - return true; - } - }); -}; + target[key] = value; + return true; + } +}); /** * Retrieves the current page compile time globals. diff --git a/kastro/crate.js b/kastro/crate.js deleted file mode 100644 index 2f74554..0000000 --- a/kastro/crate.js +++ /dev/null @@ -1,33 +0,0 @@ -import yaml from "js-yaml"; -import { readFile, readdir } from "node:fs/promises"; -import { I18nString, LangCode } from "../util/i18n"; - -/** - * @dict - * @typedef {{ - * index: string, - * codebaseLang: LangCode, - * pages: !Array - * }} - */ -const CrateRecipe = {}; - -/** - * @param {string} crateName - * @return {!Promise} - */ -const readCrateRecipe = (crateName) => readdir(crateName) - .then((/** !Array */ dir) => { - for (const file of dir) { - if (!file.startsWith(".") && file.endsWith(".yaml")) - return readFile(`${crateName}/${file}`) - .then((content) => /** @type {CrateRecipe} */(yaml.load(content))); - } - return Promise.reject(); - }); - -export { - CrateRecipe, - LangCode, - readCrateRecipe -}; diff --git a/kastro/kastro.js b/kastro/kastro.js index 4b35182..40fa87d 100644 --- a/kastro/kastro.js +++ b/kastro/kastro.js @@ -7,10 +7,10 @@ import compiler from "./compiler/compiler"; import { ttfTarget, woff2Target } from "./compiler/font"; import { inlineSvgTarget, pngTarget, svgTarget, webpTarget } from "./compiler/image"; import { pageTarget } from "./compiler/page"; +import { getGlobals } from "./compiler/pageGlobals"; import { scriptTarget } from "./compiler/script"; import { stylesheetTarget } from "./compiler/stylesheet"; import { registerTargetFunction } from "./compiler/targetRegistry"; -import { readCrateRecipe } from "./crate"; const setupKastro = () => { registerTargetFunction(".html", pageTarget); @@ -52,14 +52,22 @@ const setupKastro = () => { loader: "js" }; }); - build.onResolve({ filter: /./, namespace: "kastro" }, ({ path, importer }) => ({ - path: path.startsWith(".") ? "/" + combine(getDir(importer.replace("kastro:", "")), path) : path, - namespace: "kastro" + build.onResolve({ filter: /./, namespace: "script" }, ({ path, importer }) => ({ + path: path.startsWith(".") ? "/" + combine(getDir(importer.replace("script:", "")), path) : path, + namespace: "script" })); - build.onLoad({ filter: /.*/, namespace: "kastro" }, (args) => ({ + build.onLoad({ filter: /.*/, namespace: "script" }, (args) => ({ contents: scriptLoader.replace("SOURCE", args.path.slice(cwdLen)), loader: "js" })); + build.onResolve({ filter: /./, namespace: "worker" }, ({ path, importer }) => ({ + path: path.startsWith(".") ? "/" + combine(getDir(importer.replace("worker:", "")), path) : path, + namespace: "worker" + })); + build.onLoad({ filter: /.*/, namespace: "worker" }, (args) => ({ + contents: workerLoader.replace("SOURCE", args.path.slice(cwdLen)), + loader: "js" + })); }, }); @@ -71,39 +79,39 @@ const setupKastro = () => { } /** - * @param {string} crateName + * @param {!Object} crate * @param {compiler.BuildMode} buildMode - * @return {!Promise>} Returns a map from routes to page globals. + * @return {!Object} Returns a map from routes to page props. */ -const readCrate = (crateName, buildMode) => readCrateRecipe(crateName) - .then((crate) => { - /** @const {!Array} */ - const langs = crate.pages ? Object.keys(crate.pages[0]) : crate.languages; - const map = {}; - const add = (page, name) => { - for (const lang of langs) { - const pageProps = { - BuildMode: buildMode, - Lang: lang, - CodebaseLang: crate.codebaseLang, - Route: { ...page }, // Make a copy - assetName: page[lang], - targetName: `/build/${name || page[crate.codebaseLang]}/page-${lang}.html`, - }; - delete pageProps.Route[lang]; - map[`/${page[lang]}`] = pageProps; - } - }; - add(Object.fromEntries(langs.map(lang => [lang, lang])), crate.index); - map["/"] = map[`/${crate.codebaseLang}`]; - if (crate.pages) - for (const page of crate.pages) add(page); +const cratePageProps = (crate, buildMode) => { + /** @const {!Array} */ + const langs = crate.Page ? Object.keys(Object.values(crate.Page)[0]) : crate.Languages; + const map = {}; + const add = (page, name) => { + for (const lang of langs) { + const pageProps = { + BuildMode: buildMode, + Lang: lang, + CodebaseLang: crate.CodebaseLang, + Route: { ...page }, // Make a copy + assetName: page[lang], + targetName: `/build/${name || page[crate.CodebaseLang]}/page-${lang}.html`, + }; + delete pageProps.Route[lang]; + map[`/${page[lang]}`] = pageProps; + } + }; + if (crate.Page) + for (const [name, routes] of Object.entries(crate.Page)) + add(routes, routes == crate.Entry ? name.toLowerCase() : undefined); + map["/"] = map[`/${crate.CodebaseLang}`]; - return map; - }); + return map; +}; const serveCrate = async (crateName, buildMode) => { - const map = await readCrate(crateName, buildMode); + const crate = await import(crateName); + const map = cratePageProps(crate, buildMode); let currentPageProps; createServer({ @@ -125,23 +133,9 @@ const serveCrate = async (crateName, buildMode) => { }, transform(code, id) { - if (id.endsWith("cüzdan/birim.js")) - return code - .replace(/const Chains =.*?;/, `const Chains = ${JSON.stringify(currentPageProps.Chains)};`) - .replace(/const DefaultChain =.*?;/, `const DefaultChain = ${JSON.stringify(currentPageProps.DefaultChain)};`); - if (id.endsWith("dil/birim.js")) - return code - .replace(/const Route =.*?;/, `const Route = ${JSON.stringify(currentPageProps.Route)};`); - if (id.endsWith("util/dom.js")) - return code - .replace(/const GEN =.*?;/, `const GEN = false`) - .replace(/const Lang =.*?;/, `const Lang = "${currentPageProps.Lang}";`); - if (id.endsWith(".jsx")) { - const lines = code.split("\n"); - const filteredLines = lines.filter((line) => line.includes("util/dom") || - line.trim().startsWith("export const")); - return filteredLines.join("\n"); - } + const globals = getGlobals(); + if (crate.devModeJsTransform) + return crate.devModeJsTransform(id, code, globals); } }] }).then((vite) => vite.listen(8787)) @@ -150,6 +144,6 @@ const serveCrate = async (crateName, buildMode) => { setupKastro(); const args = parseArgs(process.argv.slice(2), "target"); -serveCrate(".", args["compiled"] +serveCrate(process.cwd() + "/crate.js", args["compiled"] ? compiler.BuildMode.Compiled : compiler.BuildMode.Dev);