Mercurial
changeset 154:bdcc610eeed8
[Markdown Converter][GuiZe] Added markdown coverter in C and wasm rule sets. Needs further view on this as I haven't taken a look. Written by Claude.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Mon, 12 Jan 2026 09:11:58 -0800 |
| parents | 790930d9bb90 |
| children | 3bb45eb67906 |
| files | .bazelrc MODULE.bazel MODULE.bazel.lock gui_ze/gui_ze.bzl markdown_converter/BUILD markdown_converter/markdown_to_html.c markdown_converter/markdown_to_html.h markdown_converter/markdown_to_html_wasm.c markdown_converter/markdown_to_html_wasm.js mrjunejune/BUILD seobeo/s_web.c |
| diffstat | 11 files changed, 1910 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/.bazelrc Sun Jan 11 08:11:24 2026 -0800 +++ b/.bazelrc Mon Jan 12 09:11:58 2026 -0800 @@ -3,3 +3,6 @@ # Suppress duplicate library warnings from openssl BCR module on macOS build:macos --linkopt=-Wl,-no_warn_duplicate_libraries + +# Wasm support? +build:wasm --platforms=@emsdk//bazel/emscripten_toolchain:wasm_platform
--- a/MODULE.bazel Sun Jan 11 08:11:24 2026 -0800 +++ b/MODULE.bazel Mon Jan 12 09:11:58 2026 -0800 @@ -3,6 +3,8 @@ bazel_dep(name = "bazel_skylib", version = "1.8.2") bazel_dep(name = "rules_shell", version = "0.6.1") bazel_dep(name = "openssl", version = "3.3.1.bcr.7") +bazel_dep(name = "emsdk", version = "4.0.17") + http_file = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
--- a/MODULE.bazel.lock Sun Jan 11 08:11:24 2026 -0800 +++ b/MODULE.bazel.lock Mon Jan 12 09:11:58 2026 -0800 @@ -17,6 +17,10 @@ "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896", "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", "https://bcr.bazel.build/modules/apple_support/1.15.1/source.json": "517f2b77430084c541bc9be2db63fdcbb7102938c5f64c17ee60ffda2e5cf07b", + "https://bcr.bazel.build/modules/aspect_bazel_lib/1.42.3/MODULE.bazel": "e4529e12d8cd5b828e2b5960d07d3ec032541740d419d7d5b859cabbf5b056f9", + "https://bcr.bazel.build/modules/aspect_bazel_lib/1.42.3/source.json": "80cb66069ad626e0921555cd2bf278286fd7763fae2450e564e351792e8303f4", + "https://bcr.bazel.build/modules/aspect_rules_js/1.42.0/MODULE.bazel": "f19e6b4a16f77f8cf3728eac1f60dbfd8e043517fd4f4dbf17a75a6c50936d62", + "https://bcr.bazel.build/modules/aspect_rules_js/1.42.0/source.json": "abbb3eac3b6af76b8ce230a9a901c6d08d93f4f5ffd55314bf630827dddee57e", "https://bcr.bazel.build/modules/bazel_features/1.1.0/MODULE.bazel": "cfd42ff3b815a5f39554d97182657f8c4b9719568eb7fded2b9135f084bf760b", "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", @@ -32,6 +36,7 @@ "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87", "https://bcr.bazel.build/modules/bazel_features/1.30.0/source.json": "b07e17f067fe4f69f90b03b36ef1e08fe0d1f3cac254c1241a1818773e3423bc", "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "https://bcr.bazel.build/modules/bazel_features/1.9.0/MODULE.bazel": "885151d58d90d8d9c811eb75e3288c11f850e1d6b481a8c9f766adee4712358b", "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", @@ -53,6 +58,8 @@ "https://bcr.bazel.build/modules/bazel_worker_java/0.0.4/source.json": "a2d30458fd86cf022c2b6331e652526fa08e17573b2f5034a9dbcacdf9c2583c", "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", + "https://bcr.bazel.build/modules/emsdk/4.0.17/MODULE.bazel": "a10c49d7063e5dffeec0c5b43753ab2575179fbb679851059861af7d2a781c6a", + "https://bcr.bazel.build/modules/emsdk/4.0.17/source.json": "8463664bc6319425d29ef0d7edd8660daf1bf0ec33c367420243d4db35e0f482", "https://bcr.bazel.build/modules/gazelle/0.32.0/MODULE.bazel": "b499f58a5d0d3537f3cf5b76d8ada18242f64ec474d8391247438bf04f58c7b8", "https://bcr.bazel.build/modules/gazelle/0.33.0/MODULE.bazel": "a13a0f279b462b784fb8dd52a4074526c4a2afe70e114c7d09066097a46b3350", "https://bcr.bazel.build/modules/gazelle/0.34.0/MODULE.bazel": "abdd8ce4d70978933209db92e436deb3a8b737859e9354fb5fd11fb5c2004c8a", @@ -170,6 +177,9 @@ "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", + "https://bcr.bazel.build/modules/rules_nodejs/5.8.2/MODULE.bazel": "6bc03c8f37f69401b888023bf511cb6ee4781433b0cb56236b2e55a21e3a026a", + "https://bcr.bazel.build/modules/rules_nodejs/6.3.2/MODULE.bazel": "42e8d5254b6135f890fecca7c8d7f95a7d27a45f8275b276f66ec337767530ef", + "https://bcr.bazel.build/modules/rules_nodejs/6.3.2/source.json": "80e0a68eb81772f1631f8b69014884eebc2474b3b3025fd19a5240ae4f76f9c9", "https://bcr.bazel.build/modules/rules_perl/0.4.1/MODULE.bazel": "4d09ad3a3cf71e606faab258a753ba9f0516b5d3c6aff9b813d06ea65c04702f", "https://bcr.bazel.build/modules/rules_perl/0.4.1/source.json": "70e943e2deea44c1b2ddfafe178a294b82f8b8a24ee25d547eaaa202142f1b4d", "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", @@ -193,7 +203,8 @@ "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7", "https://bcr.bazel.build/modules/rules_python/1.0.0/MODULE.bazel": "898a3d999c22caa585eb062b600f88654bf92efb204fa346fb55f6f8edffca43", - "https://bcr.bazel.build/modules/rules_python/1.0.0/source.json": "b0162a65c6312e45e7912e39abd1a7f8856c2c7e41ecc9b6dc688a6f6400a917", + "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13", + "https://bcr.bazel.build/modules/rules_python/1.3.0/source.json": "25932f917cd279c7baefa6cb1d3fa8750a7a29de522024449b19af6eab51f4a0", "https://bcr.bazel.build/modules/rules_robolectric/4.14.1.2/MODULE.bazel": "d44fec647d0aeb67b9f3b980cf68ba634976f3ae7ccd6c07d790b59b87a4f251", "https://bcr.bazel.build/modules/rules_robolectric/4.14.1.2/source.json": "37c10335f2361c337c5c1f34ed36d2da70534c23088062b33a8bdaab68aa9dea", "https://bcr.bazel.build/modules/rules_shell/0.1.2/MODULE.bazel": "66e4ca3ce084b04af0b9ff05ff14cab4e5df7503973818bb91cbc6cda08d32fc", @@ -207,6 +218,7 @@ "https://bcr.bazel.build/modules/rules_swift/2.1.1/source.json": "40fc69dfaac64deddbb75bd99cdac55f4427d9ca0afbe408576a65428427a186", "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", + "https://bcr.bazel.build/modules/stardoc/0.5.4/MODULE.bazel": "6569966df04610b8520957cb8e97cf2e9faac2c0309657c537ab51c16c18a2a4", "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef", "https://bcr.bazel.build/modules/stardoc/0.6.2/MODULE.bazel": "7060193196395f5dd668eda046ccbeacebfd98efc77fed418dbe2b82ffaa39fd", "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", @@ -256,6 +268,334 @@ ] } }, + "@@aspect_bazel_lib+//lib:extensions.bzl%toolchains": { + "general": { + "bzlTransitiveDigest": "x2ZXNHQB1YYLKrvA8u2W0AEQkJUyosb5KZyGwg7vTtA=", + "usagesDigest": "1c7PNX163TGNqWzfejRnWpH/hiT4/GRG0kYxuez0Uz0=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "copy_directory_darwin_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "copy_directory_darwin_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "copy_directory_freebsd_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", + "attributes": { + "platform": "freebsd_amd64" + } + }, + "copy_directory_linux_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "copy_directory_linux_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "copy_directory_windows_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "copy_directory_toolchains": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_toolchains_repo", + "attributes": { + "user_repository_name": "copy_directory" + } + }, + "copy_to_directory_darwin_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "copy_to_directory_darwin_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "copy_to_directory_freebsd_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", + "attributes": { + "platform": "freebsd_amd64" + } + }, + "copy_to_directory_linux_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "copy_to_directory_linux_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "copy_to_directory_windows_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "copy_to_directory_toolchains": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_toolchains_repo", + "attributes": { + "user_repository_name": "copy_to_directory" + } + }, + "jq_darwin_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo", + "attributes": { + "platform": "darwin_amd64", + "version": "1.6" + } + }, + "jq_darwin_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo", + "attributes": { + "platform": "darwin_arm64", + "version": "1.6" + } + }, + "jq_linux_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo", + "attributes": { + "platform": "linux_amd64", + "version": "1.6" + } + }, + "jq_windows_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo", + "attributes": { + "platform": "windows_amd64", + "version": "1.6" + } + }, + "jq": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_host_alias_repo", + "attributes": {} + }, + "jq_toolchains": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_toolchains_repo", + "attributes": { + "user_repository_name": "jq" + } + }, + "yq_darwin_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "darwin_amd64", + "version": "4.25.2" + } + }, + "yq_darwin_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "darwin_arm64", + "version": "4.25.2" + } + }, + "yq_linux_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "linux_amd64", + "version": "4.25.2" + } + }, + "yq_linux_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "linux_arm64", + "version": "4.25.2" + } + }, + "yq_linux_s390x": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "linux_s390x", + "version": "4.25.2" + } + }, + "yq_linux_ppc64le": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "linux_ppc64le", + "version": "4.25.2" + } + }, + "yq_windows_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "windows_amd64", + "version": "4.25.2" + } + }, + "yq": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_host_alias_repo", + "attributes": {} + }, + "yq_toolchains": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_toolchains_repo", + "attributes": { + "user_repository_name": "yq" + } + }, + "coreutils_darwin_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", + "attributes": { + "platform": "darwin_amd64", + "version": "0.0.16" + } + }, + "coreutils_darwin_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", + "attributes": { + "platform": "darwin_arm64", + "version": "0.0.16" + } + }, + "coreutils_linux_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", + "attributes": { + "platform": "linux_amd64", + "version": "0.0.16" + } + }, + "coreutils_linux_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", + "attributes": { + "platform": "linux_arm64", + "version": "0.0.16" + } + }, + "coreutils_windows_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", + "attributes": { + "platform": "windows_amd64", + "version": "0.0.16" + } + }, + "coreutils_toolchains": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_toolchains_repo", + "attributes": { + "user_repository_name": "coreutils" + } + }, + "bsd_tar_darwin_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "bsd_tar_darwin_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "bsd_tar_linux_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "bsd_tar_linux_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "bsd_tar_windows_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "bsd_tar_toolchains": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%tar_toolchains_repo", + "attributes": { + "user_repository_name": "bsd_tar" + } + }, + "expand_template_darwin_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "expand_template_darwin_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "expand_template_freebsd_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", + "attributes": { + "platform": "freebsd_amd64" + } + }, + "expand_template_linux_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "expand_template_linux_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "expand_template_windows_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "expand_template_toolchains": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_toolchains_repo", + "attributes": { + "user_repository_name": "expand_template" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "aspect_bazel_lib+", + "aspect_bazel_lib", + "aspect_bazel_lib+" + ], + [ + "aspect_bazel_lib+", + "bazel_skylib", + "bazel_skylib+" + ], + [ + "aspect_bazel_lib+", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, "@@rules_android+//rules/android_sdk_repository:rule.bzl%android_sdk_repository_extension": { "general": { "bzlTransitiveDigest": "NAy+0M15JNVEBb8Tny6t7j3lKqTnsAMjoBB6LJ+C370=", @@ -335,6 +675,163 @@ ] ] } + }, + "@@rules_nodejs+//nodejs:extensions.bzl%node": { + "general": { + "bzlTransitiveDigest": "rphcryfYrOY/P3emfTskC/GY5YuHcwMl2B2ncjaM8lY=", + "usagesDigest": "QSe6cWQvIHxGp1J+99fPJMNXT1Hr7PtV5kHJsfET99A=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "nodejs_linux_amd64": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories", + "attributes": { + "node_download_auth": {}, + "node_repositories": {}, + "node_urls": [ + "https://nodejs.org/dist/v{version}/{filename}" + ], + "node_version": "20.18.0", + "include_headers": false, + "platform": "linux_amd64" + } + }, + "nodejs_linux_arm64": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories", + "attributes": { + "node_download_auth": {}, + "node_repositories": {}, + "node_urls": [ + "https://nodejs.org/dist/v{version}/{filename}" + ], + "node_version": "20.18.0", + "include_headers": false, + "platform": "linux_arm64" + } + }, + "nodejs_linux_s390x": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories", + "attributes": { + "node_download_auth": {}, + "node_repositories": {}, + "node_urls": [ + "https://nodejs.org/dist/v{version}/{filename}" + ], + "node_version": "20.18.0", + "include_headers": false, + "platform": "linux_s390x" + } + }, + "nodejs_linux_ppc64le": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories", + "attributes": { + "node_download_auth": {}, + "node_repositories": {}, + "node_urls": [ + "https://nodejs.org/dist/v{version}/{filename}" + ], + "node_version": "20.18.0", + "include_headers": false, + "platform": "linux_ppc64le" + } + }, + "nodejs_darwin_amd64": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories", + "attributes": { + "node_download_auth": {}, + "node_repositories": {}, + "node_urls": [ + "https://nodejs.org/dist/v{version}/{filename}" + ], + "node_version": "20.18.0", + "include_headers": false, + "platform": "darwin_amd64" + } + }, + "nodejs_darwin_arm64": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories", + "attributes": { + "node_download_auth": {}, + "node_repositories": {}, + "node_urls": [ + "https://nodejs.org/dist/v{version}/{filename}" + ], + "node_version": "20.18.0", + "include_headers": false, + "platform": "darwin_arm64" + } + }, + "nodejs_windows_amd64": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories", + "attributes": { + "node_download_auth": {}, + "node_repositories": {}, + "node_urls": [ + "https://nodejs.org/dist/v{version}/{filename}" + ], + "node_version": "20.18.0", + "include_headers": false, + "platform": "windows_amd64" + } + }, + "nodejs": { + "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_repo_host_os_alias.bzl%nodejs_repo_host_os_alias", + "attributes": { + "user_node_repository_name": "nodejs" + } + }, + "nodejs_host": { + "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_repo_host_os_alias.bzl%nodejs_repo_host_os_alias", + "attributes": { + "user_node_repository_name": "nodejs" + } + }, + "nodejs_toolchains": { + "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_toolchains_repo.bzl%nodejs_toolchains_repo", + "attributes": { + "user_node_repository_name": "nodejs" + } + } + }, + "recordedRepoMappingEntries": [] + } + }, + "@@rules_python+//python/uv:uv.bzl%uv": { + "general": { + "bzlTransitiveDigest": "Xpqjnjzy6zZ90Es9Wa888ZLHhn7IsNGbph/e6qoxzw8=", + "usagesDigest": "vJ5RHUxAnV24M5swNGiAnkdxMx3Hp/iOLmNANTC5Xc8=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "uv": { + "repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo", + "attributes": { + "toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'", + "toolchain_names": [ + "none" + ], + "toolchain_implementations": { + "none": "'@@rules_python+//python:none'" + }, + "toolchain_compatible_with": { + "none": [ + "@platforms//:incompatible" + ] + }, + "toolchain_target_settings": {} + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_python+", + "platforms", + "platforms" + ] + ] + } } } }
--- a/gui_ze/gui_ze.bzl Sun Jan 11 08:11:24 2026 -0800 +++ b/gui_ze/gui_ze.bzl Mon Jan 12 09:11:58 2026 -0800 @@ -1,3 +1,69 @@ +def _wasm_binary_impl(ctx): + """ + Compile C source to WASM using clang --target=wasm32. + No libc - suitable for standalone WASM modules. + + Requires LLVM with wasm32 support (e.g., Homebrew LLVM on macOS). + """ + src = ctx.file.src + out = ctx.actions.declare_file(ctx.label.name + ".wasm") + + # Shell script to find clang with wasm support and set PATH for wasm-ld + setup_cmd = """ + export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH" + if [ -x /opt/homebrew/opt/llvm/bin/clang ]; then + CLANG=/opt/homebrew/opt/llvm/bin/clang + elif [ -x /usr/local/opt/llvm/bin/clang ]; then + CLANG=/usr/local/opt/llvm/bin/clang + else + CLANG=clang + fi + """ + + # Build clang command + cmd_parts = [ + setup_cmd, + "$CLANG", + "--target=wasm32", + "-nostdlib", + "-O2", + "-Wl,--no-entry", + "-Wl,--export-dynamic", + ] + + # Add exported functions + for fn in ctx.attr.exports: + cmd_parts.append("-Wl,--export=" + fn) + + cmd_parts.append("-o") + cmd_parts.append(out.path) + cmd_parts.append(src.path) + + ctx.actions.run_shell( + inputs = [src], + outputs = [out], + command = " ".join(cmd_parts), + progress_message = "Compiling {} to WASM".format(src.basename), + execution_requirements = {"no-sandbox": "1"}, + ) + + return [DefaultInfo(files = depset([out]))] + +wasm_binary = rule( + implementation = _wasm_binary_impl, + attrs = { + "src": attr.label( + allow_single_file = [".c"], + mandatory = True, + doc = "The C source file to compile", + ), + "exports": attr.string_list( + default = [], + doc = "List of function names to export (without leading underscore)", + ), + }, +) + def _foo_impl(ctx): out = ctx.actions.declare_file(ctx.label.name) ctx.actions.write(
--- a/markdown_converter/BUILD Sun Jan 11 08:11:24 2026 -0800 +++ b/markdown_converter/BUILD Mon Jan 12 09:11:58 2026 -0800 @@ -1,3 +1,7 @@ +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("//gui_ze:gui_ze.bzl", "wasm_binary") + +# JavaScript implementation (original) filegroup( name = "markdown_to_html", srcs = glob([ @@ -6,4 +10,26 @@ visibility = ["//visibility:public"], ) +# C implementation for native use +cc_library( + name = "markdown_to_html_c", + srcs = ["markdown_to_html.c"], + hdrs = ["markdown_to_html.h"], + visibility = ["//visibility:public"], +) +# WASM binary for browser FFI +wasm_binary( + name = "markdown_to_html_wasm", + src = "markdown_to_html_wasm.c", + exports = [ + "malloc", + "free", + "heap_reset", + "markdown_to_html", + "markdown_strlen", + ], + visibility = ["//visibility:public"], +) + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/markdown_converter/markdown_to_html.c Mon Jan 12 09:11:58 2026 -0800 @@ -0,0 +1,545 @@ +/** + * Markdown to HTML Converter - C Implementation + * Supports: headers, bold, italic, links, lists, code blocks, blockquotes, horizontal rules + */ + +#include "markdown_to_html.h" +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> + +#define INITIAL_BUFFER_SIZE 4096 + +// String buffer for building HTML output +typedef struct { + char *data; + size_t length; + size_t capacity; +} StringBuffer; + +static StringBuffer *buffer_create(size_t initial_capacity) +{ + StringBuffer *buf = (StringBuffer *)malloc(sizeof(StringBuffer)); + if (!buf) return NULL; + + buf->data = (char *)malloc(initial_capacity); + if (!buf->data) { + free(buf); + return NULL; + } + buf->data[0] = '\0'; + buf->length = 0; + buf->capacity = initial_capacity; + return buf; +} + +static void buffer_grow(StringBuffer *buf, size_t needed) +{ + if (buf->length + needed + 1 > buf->capacity) { + size_t new_capacity = buf->capacity * 2; + while (new_capacity < buf->length + needed + 1) + new_capacity *= 2; + + char *new_data = (char *)realloc(buf->data, new_capacity); + if (new_data) { + buf->data = new_data; + buf->capacity = new_capacity; + } + } +} + +static void buffer_append(StringBuffer *buf, const char *str) +{ + size_t len = strlen(str); + buffer_grow(buf, len); + memcpy(buf->data + buf->length, str, len + 1); + buf->length += len; +} + +static void buffer_append_n(StringBuffer *buf, const char *str, size_t n) +{ + buffer_grow(buf, n); + memcpy(buf->data + buf->length, str, n); + buf->length += n; + buf->data[buf->length] = '\0'; +} + +static void buffer_append_char(StringBuffer *buf, char c) +{ + buffer_grow(buf, 1); + buf->data[buf->length++] = c; + buf->data[buf->length] = '\0'; +} + +static void buffer_free(StringBuffer *buf) +{ + if (buf) { + free(buf->data); + free(buf); + } +} + +// Check if line starts with pattern (after trimming whitespace) +static int starts_with(const char *line, const char *pattern) +{ + while (*line && isspace((unsigned char)*line)) line++; + return strncmp(line, pattern, strlen(pattern)) == 0; +} + +// Count leading # characters +static int count_heading_level(const char *line) +{ + int count = 0; + while (*line && isspace((unsigned char)*line)) line++; + while (line[count] == '#' && count < 6) count++; + if (count > 0 && line[count] == ' ') return count; + return 0; +} + +// Skip whitespace +static const char *skip_whitespace(const char *str) +{ + while (*str && isspace((unsigned char)*str)) str++; + return str; +} + +// Check if line is empty (only whitespace) +static int is_empty_line(const char *line) +{ + while (*line) { + if (!isspace((unsigned char)*line)) return 0; + line++; + } + return 1; +} + +// Check if line is horizontal rule (---, ***, ___) +static int is_horizontal_rule(const char *line) +{ + line = skip_whitespace(line); + char first = *line; + if (first != '-' && first != '*' && first != '_') return 0; + + int count = 0; + while (*line) { + if (*line == first) count++; + else if (!isspace((unsigned char)*line)) return 0; + line++; + } + return count >= 3; +} + +// Check if line is unordered list item +static int is_unordered_list(const char *line) +{ + line = skip_whitespace(line); + return (*line == '-' || *line == '*' || *line == '+') && line[1] == ' '; +} + +// Check if line is ordered list item +static int is_ordered_list(const char *line) +{ + line = skip_whitespace(line); + while (*line && isdigit((unsigned char)*line)) line++; + return *line == '.' && line[1] == ' '; +} + +// Process inline markdown (bold, italic, code, links, strikethrough) +static void process_inline(StringBuffer *buf, const char *text, size_t len) +{ + size_t i = 0; + + while (i < len) { + // Links: [text](url) + if (text[i] == '[') { + size_t link_start = i + 1; + size_t link_end = link_start; + while (link_end < len && text[link_end] != ']') link_end++; + + if (link_end < len && link_end + 1 < len && text[link_end + 1] == '(') { + size_t url_start = link_end + 2; + size_t url_end = url_start; + while (url_end < len && text[url_end] != ')') url_end++; + + if (url_end < len) { + buffer_append(buf, "<a href=\""); + buffer_append_n(buf, text + url_start, url_end - url_start); + buffer_append(buf, "\">"); + buffer_append_n(buf, text + link_start, link_end - link_start); + buffer_append(buf, "</a>"); + i = url_end + 1; + continue; + } + } + } + + // Images:  + if (text[i] == '!' && i + 1 < len && text[i + 1] == '[') { + size_t alt_start = i + 2; + size_t alt_end = alt_start; + while (alt_end < len && text[alt_end] != ']') alt_end++; + + if (alt_end < len && alt_end + 1 < len && text[alt_end + 1] == '(') { + size_t url_start = alt_end + 2; + size_t url_end = url_start; + while (url_end < len && text[url_end] != ')') url_end++; + + if (url_end < len) { + buffer_append(buf, "<img src=\""); + buffer_append_n(buf, text + url_start, url_end - url_start); + buffer_append(buf, "\" alt=\""); + buffer_append_n(buf, text + alt_start, alt_end - alt_start); + buffer_append(buf, "\">"); + i = url_end + 1; + continue; + } + } + } + + // Bold: **text** or __text__ + if ((text[i] == '*' && i + 1 < len && text[i + 1] == '*') || + (text[i] == '_' && i + 1 < len && text[i + 1] == '_')) { + char marker = text[i]; + size_t start = i + 2; + size_t end = start; + while (end + 1 < len && !(text[end] == marker && text[end + 1] == marker)) end++; + + if (end + 1 < len) { + buffer_append(buf, "<strong>"); + process_inline(buf, text + start, end - start); + buffer_append(buf, "</strong>"); + i = end + 2; + continue; + } + } + + // Strikethrough: ~~text~~ + if (text[i] == '~' && i + 1 < len && text[i + 1] == '~') { + size_t start = i + 2; + size_t end = start; + while (end + 1 < len && !(text[end] == '~' && text[end + 1] == '~')) end++; + + if (end + 1 < len) { + buffer_append(buf, "<del>"); + process_inline(buf, text + start, end - start); + buffer_append(buf, "</del>"); + i = end + 2; + continue; + } + } + + // Italic: *text* or _text_ + if ((text[i] == '*' || text[i] == '_') && i + 1 < len && !isspace((unsigned char)text[i + 1])) { + char marker = text[i]; + size_t start = i + 1; + size_t end = start; + while (end < len && text[end] != marker) end++; + + if (end < len && end > start) { + buffer_append(buf, "<em>"); + process_inline(buf, text + start, end - start); + buffer_append(buf, "</em>"); + i = end + 1; + continue; + } + } + + // Inline code: `code` + if (text[i] == '`') { + size_t start = i + 1; + size_t end = start; + while (end < len && text[end] != '`') end++; + + if (end < len) { + buffer_append(buf, "<code>"); + buffer_append_n(buf, text + start, end - start); + buffer_append(buf, "</code>"); + i = end + 1; + continue; + } + } + + // HTML escape special characters + if (text[i] == '<') { + buffer_append(buf, "<"); + } else if (text[i] == '>') { + buffer_append(buf, ">"); + } else if (text[i] == '&') { + buffer_append(buf, "&"); + } else { + buffer_append_char(buf, text[i]); + } + i++; + } +} + +// Convert markdown to HTML +MDAPI char *markdown_to_html(const char *markdown) +{ + if (!markdown) return NULL; + + StringBuffer *buf = buffer_create(INITIAL_BUFFER_SIZE); + if (!buf) return NULL; + + const char *ptr = markdown; + const char *line_start; + + while (*ptr) { + line_start = ptr; + + // Find end of line + while (*ptr && *ptr != '\n') ptr++; + size_t line_len = ptr - line_start; + + // Create null-terminated line copy + char *line = (char *)malloc(line_len + 1); + if (!line) { + buffer_free(buf); + return NULL; + } + memcpy(line, line_start, line_len); + line[line_len] = '\0'; + + // Skip empty lines + if (is_empty_line(line)) { + free(line); + if (*ptr == '\n') ptr++; + continue; + } + + // Headings: # H1, ## H2, etc. + int heading_level = count_heading_level(line); + if (heading_level > 0) { + const char *content = skip_whitespace(line); + while (*content == '#') content++; + content = skip_whitespace(content); + + char tag[8]; + snprintf(tag, sizeof(tag), "<h%d>", heading_level); + buffer_append(buf, tag); + process_inline(buf, content, strlen(content)); + snprintf(tag, sizeof(tag), "</h%d>", heading_level); + buffer_append(buf, tag); + + free(line); + if (*ptr == '\n') ptr++; + continue; + } + + // Code block: ``` + if (starts_with(line, "```")) { + buffer_append(buf, "<pre><code>"); + free(line); + if (*ptr == '\n') ptr++; + + // Collect code content + while (*ptr) { + line_start = ptr; + while (*ptr && *ptr != '\n') ptr++; + line_len = ptr - line_start; + + line = (char *)malloc(line_len + 1); + if (!line) break; + memcpy(line, line_start, line_len); + line[line_len] = '\0'; + + if (starts_with(line, "```")) { + free(line); + if (*ptr == '\n') ptr++; + break; + } + + // Escape HTML in code blocks + for (size_t i = 0; i < line_len; i++) { + if (line[i] == '<') buffer_append(buf, "<"); + else if (line[i] == '>') buffer_append(buf, ">"); + else if (line[i] == '&') buffer_append(buf, "&"); + else buffer_append_char(buf, line[i]); + } + buffer_append_char(buf, '\n'); + + free(line); + if (*ptr == '\n') ptr++; + } + + buffer_append(buf, "</code></pre>"); + continue; + } + + // Blockquote: > + if (starts_with(line, ">")) { + buffer_append(buf, "<blockquote>"); + + while (1) { + const char *content = skip_whitespace(line); + if (*content == '>') content++; + content = skip_whitespace(content); + process_inline(buf, content, strlen(content)); + buffer_append_char(buf, ' '); + + free(line); + if (*ptr == '\n') ptr++; + + // Check next line + if (!*ptr) break; + line_start = ptr; + while (*ptr && *ptr != '\n') ptr++; + line_len = ptr - line_start; + + line = (char *)malloc(line_len + 1); + if (!line) break; + memcpy(line, line_start, line_len); + line[line_len] = '\0'; + + if (!starts_with(line, ">")) { + // Put back the line pointer + ptr = line_start; + free(line); + break; + } + } + + buffer_append(buf, "</blockquote>"); + continue; + } + + // Horizontal rule + if (is_horizontal_rule(line)) { + buffer_append(buf, "<hr>"); + free(line); + if (*ptr == '\n') ptr++; + continue; + } + + // Unordered list + if (is_unordered_list(line)) { + buffer_append(buf, "<ul>"); + + while (1) { + const char *content = skip_whitespace(line); + content += 2; // Skip "- " or "* " or "+ " + + buffer_append(buf, "<li>"); + process_inline(buf, content, strlen(content)); + buffer_append(buf, "</li>"); + + free(line); + if (*ptr == '\n') ptr++; + + // Check next line + if (!*ptr) break; + line_start = ptr; + while (*ptr && *ptr != '\n') ptr++; + line_len = ptr - line_start; + + line = (char *)malloc(line_len + 1); + if (!line) break; + memcpy(line, line_start, line_len); + line[line_len] = '\0'; + + if (!is_unordered_list(line)) { + ptr = line_start; + free(line); + break; + } + } + + buffer_append(buf, "</ul>"); + continue; + } + + // Ordered list + if (is_ordered_list(line)) { + buffer_append(buf, "<ol>"); + + while (1) { + const char *content = skip_whitespace(line); + while (*content && isdigit((unsigned char)*content)) content++; + if (*content == '.') content++; + content = skip_whitespace(content); + + buffer_append(buf, "<li>"); + process_inline(buf, content, strlen(content)); + buffer_append(buf, "</li>"); + + free(line); + if (*ptr == '\n') ptr++; + + // Check next line + if (!*ptr) break; + line_start = ptr; + while (*ptr && *ptr != '\n') ptr++; + line_len = ptr - line_start; + + line = (char *)malloc(line_len + 1); + if (!line) break; + memcpy(line, line_start, line_len); + line[line_len] = '\0'; + + if (!is_ordered_list(line)) { + ptr = line_start; + free(line); + break; + } + } + + buffer_append(buf, "</ol>"); + continue; + } + + // Regular paragraph + buffer_append(buf, "<p>"); + + while (1) { + const char *content = skip_whitespace(line); + process_inline(buf, content, strlen(content)); + + free(line); + if (*ptr == '\n') ptr++; + + // Check next line - continue paragraph if not special + if (!*ptr) break; + line_start = ptr; + while (*ptr && *ptr != '\n') ptr++; + line_len = ptr - line_start; + + line = (char *)malloc(line_len + 1); + if (!line) break; + memcpy(line, line_start, line_len); + line[line_len] = '\0'; + + if (is_empty_line(line) || + count_heading_level(line) > 0 || + starts_with(line, "```") || + starts_with(line, ">") || + is_horizontal_rule(line) || + is_unordered_list(line) || + is_ordered_list(line)) { + ptr = line_start; + free(line); + break; + } + + buffer_append_char(buf, ' '); + } + + buffer_append(buf, "</p>"); + } + + char *result = buf->data; + free(buf); // Free struct but not data + return result; +} + +// Free the returned HTML string +MDAPI void markdown_free(char *html) +{ + free(html); +} + +// Get length of HTML string (for WASM memory allocation) +MDAPI size_t markdown_get_length(const char *html) +{ + return html ? strlen(html) : 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/markdown_converter/markdown_to_html.h Mon Jan 12 09:11:58 2026 -0800 @@ -0,0 +1,60 @@ +#ifndef MARKDOWN_TO_HTML_H +#define MARKDOWN_TO_HTML_H + +#include <stddef.h> + +// Export macro for WASM/Emscripten +#ifdef __EMSCRIPTEN__ + #include <emscripten.h> + #define MDAPI EMSCRIPTEN_KEEPALIVE +#else + #ifdef _WIN32 + #ifdef MARKDOWN_EXPORTS + #define MDAPI __declspec(dllexport) + #else + #define MDAPI __declspec(dllimport) + #endif + #else + #define MDAPI extern + #endif +#endif + +/** + * Convert markdown string to HTML string. + * + * @param markdown The input markdown string (null-terminated) + * @return Newly allocated HTML string. Caller must free with markdown_free(). + * Returns NULL on allocation failure. + * + * Supported markdown features: + * - Headers: # H1, ## H2, ... ###### H6 + * - Bold: **text** or __text__ + * - Italic: *text* or _text_ + * - Strikethrough: ~~text~~ + * - Links: [text](url) + * - Images:  + * - Inline code: `code` + * - Code blocks: ```code``` + * - Unordered lists: -, *, + + * - Ordered lists: 1., 2., etc. + * - Blockquotes: > text + * - Horizontal rules: ---, ***, ___ + */ +MDAPI char *markdown_to_html(const char *markdown); + +/** + * Free HTML string returned by markdown_to_html. + * + * @param html The HTML string to free + */ +MDAPI void markdown_free(char *html); + +/** + * Get length of HTML string (useful for WASM memory operations). + * + * @param html The HTML string + * @return Length of the string, or 0 if NULL + */ +MDAPI size_t markdown_get_length(const char *html); + +#endif // MARKDOWN_TO_HTML_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/markdown_converter/markdown_to_html_wasm.c Mon Jan 12 09:11:58 2026 -0800 @@ -0,0 +1,565 @@ +/** + * Markdown to HTML Converter - Standalone WASM Implementation + * No libc dependencies - can be compiled with: clang --target=wasm32 + */ + +#define WASM_EXPORT __attribute__((visibility("default"))) + +typedef unsigned long size_t; +typedef int int32_t; + +// Simple bump allocator for WASM +#define HEAP_SIZE (1024 * 1024) // 1MB heap +static char heap[HEAP_SIZE]; +static size_t heap_offset = 0; + +WASM_EXPORT void *malloc(size_t size) +{ + // Align to 8 bytes + size_t aligned_offset = (heap_offset + 7) & ~7; + if (aligned_offset + size > HEAP_SIZE) return 0; + + void *ptr = &heap[aligned_offset]; + heap_offset = aligned_offset + size; + return ptr; +} + +WASM_EXPORT void free(void *ptr) +{ + // Simple bump allocator - no actual free + (void)ptr; +} + +WASM_EXPORT void heap_reset(void) +{ + heap_offset = 0; +} + +// String functions +static size_t strlen(const char *s) +{ + size_t len = 0; + while (s[len]) len++; + return len; +} + +static void *memcpy(void *dest, const void *src, size_t n) +{ + char *d = (char *)dest; + const char *s = (const char *)src; + while (n--) *d++ = *s++; + return dest; +} + +static int isspace_c(int c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'; +} + +static int isdigit_c(int c) +{ + return c >= '0' && c <= '9'; +} + +// String buffer for building HTML output +typedef struct { + char *data; + size_t length; + size_t capacity; +} StringBuffer; + +static StringBuffer *buffer_create(size_t initial_capacity) +{ + StringBuffer *buf = (StringBuffer *)malloc(sizeof(StringBuffer)); + if (!buf) return 0; + + buf->data = (char *)malloc(initial_capacity); + if (!buf->data) return 0; + + buf->data[0] = '\0'; + buf->length = 0; + buf->capacity = initial_capacity; + return buf; +} + +static void buffer_grow(StringBuffer *buf, size_t needed) +{ + if (buf->length + needed + 1 > buf->capacity) { + size_t new_capacity = buf->capacity * 2; + while (new_capacity < buf->length + needed + 1) + new_capacity *= 2; + + char *new_data = (char *)malloc(new_capacity); + if (new_data) { + memcpy(new_data, buf->data, buf->length + 1); + buf->data = new_data; + buf->capacity = new_capacity; + } + } +} + +static void buffer_append(StringBuffer *buf, const char *str) +{ + size_t len = strlen(str); + buffer_grow(buf, len); + memcpy(buf->data + buf->length, str, len + 1); + buf->length += len; +} + +static void buffer_append_n(StringBuffer *buf, const char *str, size_t n) +{ + buffer_grow(buf, n); + memcpy(buf->data + buf->length, str, n); + buf->length += n; + buf->data[buf->length] = '\0'; +} + +static void buffer_append_char(StringBuffer *buf, char c) +{ + buffer_grow(buf, 1); + buf->data[buf->length++] = c; + buf->data[buf->length] = '\0'; +} + +// Check if line starts with pattern (after trimming whitespace) +static int starts_with(const char *line, const char *pattern) +{ + while (*line && isspace_c(*line)) line++; + size_t plen = strlen(pattern); + for (size_t i = 0; i < plen; i++) { + if (line[i] != pattern[i]) return 0; + } + return 1; +} + +// Count leading # characters +static int count_heading_level(const char *line) +{ + int count = 0; + while (*line && isspace_c(*line)) line++; + while (line[count] == '#' && count < 6) count++; + if (count > 0 && line[count] == ' ') return count; + return 0; +} + +// Skip whitespace +static const char *skip_whitespace(const char *str) +{ + while (*str && isspace_c(*str)) str++; + return str; +} + +// Check if line is empty +static int is_empty_line(const char *line) +{ + while (*line) { + if (!isspace_c(*line)) return 0; + line++; + } + return 1; +} + +// Check if line is horizontal rule +static int is_horizontal_rule(const char *line) +{ + line = skip_whitespace(line); + char first = *line; + if (first != '-' && first != '*' && first != '_') return 0; + + int count = 0; + while (*line) { + if (*line == first) count++; + else if (!isspace_c(*line)) return 0; + line++; + } + return count >= 3; +} + +// Check if line is unordered list item +static int is_unordered_list(const char *line) +{ + line = skip_whitespace(line); + return (*line == '-' || *line == '*' || *line == '+') && line[1] == ' '; +} + +// Check if line is ordered list item +static int is_ordered_list(const char *line) +{ + line = skip_whitespace(line); + while (*line && isdigit_c(*line)) line++; + return *line == '.' && line[1] == ' '; +} + +// Process inline markdown +static void process_inline(StringBuffer *buf, const char *text, size_t len) +{ + size_t i = 0; + + while (i < len) { + // Links: [text](url) + if (text[i] == '[') { + size_t link_start = i + 1; + size_t link_end = link_start; + while (link_end < len && text[link_end] != ']') link_end++; + + if (link_end < len && link_end + 1 < len && text[link_end + 1] == '(') { + size_t url_start = link_end + 2; + size_t url_end = url_start; + while (url_end < len && text[url_end] != ')') url_end++; + + if (url_end < len) { + buffer_append(buf, "<a href=\""); + buffer_append_n(buf, text + url_start, url_end - url_start); + buffer_append(buf, "\">"); + buffer_append_n(buf, text + link_start, link_end - link_start); + buffer_append(buf, "</a>"); + i = url_end + 1; + continue; + } + } + } + + // Images:  + if (text[i] == '!' && i + 1 < len && text[i + 1] == '[') { + size_t alt_start = i + 2; + size_t alt_end = alt_start; + while (alt_end < len && text[alt_end] != ']') alt_end++; + + if (alt_end < len && alt_end + 1 < len && text[alt_end + 1] == '(') { + size_t url_start = alt_end + 2; + size_t url_end = url_start; + while (url_end < len && text[url_end] != ')') url_end++; + + if (url_end < len) { + buffer_append(buf, "<img src=\""); + buffer_append_n(buf, text + url_start, url_end - url_start); + buffer_append(buf, "\" alt=\""); + buffer_append_n(buf, text + alt_start, alt_end - alt_start); + buffer_append(buf, "\">"); + i = url_end + 1; + continue; + } + } + } + + // Bold: **text** or __text__ + if ((text[i] == '*' && i + 1 < len && text[i + 1] == '*') || + (text[i] == '_' && i + 1 < len && text[i + 1] == '_')) { + char marker = text[i]; + size_t start = i + 2; + size_t end = start; + while (end + 1 < len && !(text[end] == marker && text[end + 1] == marker)) end++; + + if (end + 1 < len) { + buffer_append(buf, "<strong>"); + process_inline(buf, text + start, end - start); + buffer_append(buf, "</strong>"); + i = end + 2; + continue; + } + } + + // Strikethrough: ~~text~~ + if (text[i] == '~' && i + 1 < len && text[i + 1] == '~') { + size_t start = i + 2; + size_t end = start; + while (end + 1 < len && !(text[end] == '~' && text[end + 1] == '~')) end++; + + if (end + 1 < len) { + buffer_append(buf, "<del>"); + process_inline(buf, text + start, end - start); + buffer_append(buf, "</del>"); + i = end + 2; + continue; + } + } + + // Italic: *text* or _text_ + if ((text[i] == '*' || text[i] == '_') && i + 1 < len && !isspace_c(text[i + 1])) { + char marker = text[i]; + size_t start = i + 1; + size_t end = start; + while (end < len && text[end] != marker) end++; + + if (end < len && end > start) { + buffer_append(buf, "<em>"); + process_inline(buf, text + start, end - start); + buffer_append(buf, "</em>"); + i = end + 1; + continue; + } + } + + // Inline code: `code` + if (text[i] == '`') { + size_t start = i + 1; + size_t end = start; + while (end < len && text[end] != '`') end++; + + if (end < len) { + buffer_append(buf, "<code>"); + buffer_append_n(buf, text + start, end - start); + buffer_append(buf, "</code>"); + i = end + 1; + continue; + } + } + + // HTML escape + if (text[i] == '<') { + buffer_append(buf, "<"); + } else if (text[i] == '>') { + buffer_append(buf, ">"); + } else if (text[i] == '&') { + buffer_append(buf, "&"); + } else { + buffer_append_char(buf, text[i]); + } + i++; + } +} + +// Append heading tag +static void append_heading_tag(StringBuffer *buf, int level, int closing) +{ + buffer_append_char(buf, '<'); + if (closing) buffer_append_char(buf, '/'); + buffer_append_char(buf, 'h'); + buffer_append_char(buf, '0' + level); + buffer_append_char(buf, '>'); +} + +// Convert markdown to HTML +WASM_EXPORT char *markdown_to_html(const char *markdown) +{ + if (!markdown) return 0; + + StringBuffer *buf = buffer_create(4096); + if (!buf) return 0; + + const char *ptr = markdown; + const char *line_start; + + while (*ptr) { + line_start = ptr; + + // Find end of line + while (*ptr && *ptr != '\n') ptr++; + size_t line_len = ptr - line_start; + + // Create line copy + char *line = (char *)malloc(line_len + 1); + if (!line) return buf->data; + memcpy(line, line_start, line_len); + line[line_len] = '\0'; + + // Skip empty lines + if (is_empty_line(line)) { + if (*ptr == '\n') ptr++; + continue; + } + + // Headings + int heading_level = count_heading_level(line); + if (heading_level > 0) { + const char *content = skip_whitespace(line); + while (*content == '#') content++; + content = skip_whitespace(content); + + append_heading_tag(buf, heading_level, 0); + process_inline(buf, content, strlen(content)); + append_heading_tag(buf, heading_level, 1); + + if (*ptr == '\n') ptr++; + continue; + } + + // Code block + if (starts_with(line, "```")) { + buffer_append(buf, "<pre><code>"); + if (*ptr == '\n') ptr++; + + while (*ptr) { + line_start = ptr; + while (*ptr && *ptr != '\n') ptr++; + line_len = ptr - line_start; + + char *code_line = (char *)malloc(line_len + 1); + if (!code_line) break; + memcpy(code_line, line_start, line_len); + code_line[line_len] = '\0'; + + if (starts_with(code_line, "```")) { + if (*ptr == '\n') ptr++; + break; + } + + for (size_t i = 0; i < line_len; i++) { + if (code_line[i] == '<') buffer_append(buf, "<"); + else if (code_line[i] == '>') buffer_append(buf, ">"); + else if (code_line[i] == '&') buffer_append(buf, "&"); + else buffer_append_char(buf, code_line[i]); + } + buffer_append_char(buf, '\n'); + + if (*ptr == '\n') ptr++; + } + + buffer_append(buf, "</code></pre>"); + continue; + } + + // Blockquote + if (starts_with(line, ">")) { + buffer_append(buf, "<blockquote>"); + + while (1) { + const char *content = skip_whitespace(line); + if (*content == '>') content++; + content = skip_whitespace(content); + process_inline(buf, content, strlen(content)); + buffer_append_char(buf, ' '); + + if (*ptr == '\n') ptr++; + if (!*ptr) break; + + line_start = ptr; + while (*ptr && *ptr != '\n') ptr++; + line_len = ptr - line_start; + + line = (char *)malloc(line_len + 1); + if (!line) break; + memcpy(line, line_start, line_len); + line[line_len] = '\0'; + + if (!starts_with(line, ">")) { + ptr = line_start; + break; + } + } + + buffer_append(buf, "</blockquote>"); + continue; + } + + // Horizontal rule + if (is_horizontal_rule(line)) { + buffer_append(buf, "<hr>"); + if (*ptr == '\n') ptr++; + continue; + } + + // Unordered list + if (is_unordered_list(line)) { + buffer_append(buf, "<ul>"); + + while (1) { + const char *content = skip_whitespace(line); + content += 2; + + buffer_append(buf, "<li>"); + process_inline(buf, content, strlen(content)); + buffer_append(buf, "</li>"); + + if (*ptr == '\n') ptr++; + if (!*ptr) break; + + line_start = ptr; + while (*ptr && *ptr != '\n') ptr++; + line_len = ptr - line_start; + + line = (char *)malloc(line_len + 1); + if (!line) break; + memcpy(line, line_start, line_len); + line[line_len] = '\0'; + + if (!is_unordered_list(line)) { + ptr = line_start; + break; + } + } + + buffer_append(buf, "</ul>"); + continue; + } + + // Ordered list + if (is_ordered_list(line)) { + buffer_append(buf, "<ol>"); + + while (1) { + const char *content = skip_whitespace(line); + while (*content && isdigit_c(*content)) content++; + if (*content == '.') content++; + content = skip_whitespace(content); + + buffer_append(buf, "<li>"); + process_inline(buf, content, strlen(content)); + buffer_append(buf, "</li>"); + + if (*ptr == '\n') ptr++; + if (!*ptr) break; + + line_start = ptr; + while (*ptr && *ptr != '\n') ptr++; + line_len = ptr - line_start; + + line = (char *)malloc(line_len + 1); + if (!line) break; + memcpy(line, line_start, line_len); + line[line_len] = '\0'; + + if (!is_ordered_list(line)) { + ptr = line_start; + break; + } + } + + buffer_append(buf, "</ol>"); + continue; + } + + // Paragraph + buffer_append(buf, "<p>"); + + while (1) { + const char *content = skip_whitespace(line); + process_inline(buf, content, strlen(content)); + + if (*ptr == '\n') ptr++; + if (!*ptr) break; + + line_start = ptr; + while (*ptr && *ptr != '\n') ptr++; + line_len = ptr - line_start; + + line = (char *)malloc(line_len + 1); + if (!line) break; + memcpy(line, line_start, line_len); + line[line_len] = '\0'; + + if (is_empty_line(line) || + count_heading_level(line) > 0 || + starts_with(line, "```") || + starts_with(line, ">") || + is_horizontal_rule(line) || + is_unordered_list(line) || + is_ordered_list(line)) { + ptr = line_start; + break; + } + + buffer_append_char(buf, ' '); + } + + buffer_append(buf, "</p>"); + } + + return buf->data; +} + +// Get string length (for JS interop) +WASM_EXPORT size_t markdown_strlen(const char *str) +{ + return str ? strlen(str) : 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/markdown_converter/markdown_to_html_wasm.js Mon Jan 12 09:11:58 2026 -0800 @@ -0,0 +1,143 @@ +/** + * Markdown to HTML Converter - WASM FFI Wrapper + * Loads the C implementation via WebAssembly and provides JavaScript API + * + * Build the WASM with: bazel build //markdown_converter:markdown_to_html_wasm + */ + +class MarkdownConverterWasm { + constructor() { + this.wasm = undefined; + this.ready = false; + } + + /** + * Initialize the WASM module + * @param {string} wasmPath - Path to the .wasm file + * @returns {Promise<void>} + */ + async init(wasmPath = '/markdown_to_html_wasm.wasm') { + if (this.ready) return; + + try { + this.wasm = await WebAssembly.instantiateStreaming(fetch(wasmPath), { + env: {} + }); + this.ready = true; + } catch (err) { + console.error('Failed to load markdown WASM module:', err); + throw err; + } + } + + /** + * Write string to WASM memory + * @private + */ + _writeString(str) { + const encoder = new TextEncoder(); + const bytes = encoder.encode(str + '\0'); + const ptr = this.wasm.instance.exports.malloc(bytes.length); + const memory = new Uint8Array(this.wasm.instance.exports.memory.buffer); + memory.set(bytes, ptr); + return ptr; + } + + /** + * Read string from WASM memory + * @private + */ + _readString(ptr) { + const memory = new Uint8Array(this.wasm.instance.exports.memory.buffer); + let end = ptr; + while (memory[end] !== 0) end++; + const bytes = memory.slice(ptr, end); + const decoder = new TextDecoder(); + return decoder.decode(bytes); + } + + /** + * Reset the WASM heap (call between conversions to reclaim memory) + */ + resetHeap() { + if (this.ready) { + this.wasm.instance.exports.heap_reset(); + } + } + + /** + * Convert markdown string to HTML string using WASM + * @param {string} markdown - The markdown text to convert + * @returns {string} The converted HTML + */ + convert(markdown) { + if (!this.ready) { + throw new Error('WASM module not initialized. Call init() first.'); + } + + // Reset heap before each conversion to reclaim memory + this.resetHeap(); + + // Write markdown to WASM memory + const inputPtr = this._writeString(markdown); + + // Call the C function + const outputPtr = this.wasm.instance.exports.markdown_to_html(inputPtr); + + // Read the result + const html = this._readString(outputPtr); + + return html; + } + + /** + * Convert markdown to DOM elements (compatible with original API) + * @param {string} markdown - The markdown text to convert + * @returns {Array<HTMLElement>} Array of DOM elements + */ + convertToElements(markdown) { + const html = this.convert(markdown); + const template = document.createElement('template'); + template.innerHTML = html; + return Array.from(template.content.children); + } +} + +// Singleton instance +const markdownWasm = new MarkdownConverterWasm(); + +/** + * Convert markdown to DOM elements (WASM version) + * Compatible with original markdownConverter() API + * @param {string} value - Markdown string + * @returns {Promise<Array<HTMLElement>>} Array of DOM elements + */ +async function markdownConverterWasm(value) { + if (!markdownWasm.ready) { + await markdownWasm.init(); + } + return markdownWasm.convertToElements(value); +} + +/** + * Render markdown to a container element (WASM version) + * Compatible with original renderMarkdown() API + * @param {HTMLElement} container - Container element + * @param {string} markdown - Markdown string + */ +async function renderMarkdownWasm(container, markdown) { + if (!markdownWasm.ready) { + await markdownWasm.init(); + } + container.innerHTML = markdownWasm.convert(markdown); +} + +// Export for use in other files +if (typeof module !== 'undefined' && module.exports) { + module.exports = { + MarkdownConverterWasm, + markdownWasm, + markdownConverterWasm, + renderMarkdownWasm + }; +}
--- a/mrjunejune/BUILD Sun Jan 11 08:11:24 2026 -0800 +++ b/mrjunejune/BUILD Mon Jan 12 09:11:58 2026 -0800 @@ -15,6 +15,7 @@ name = "compiled_ts", srcs = [ "//markdown_converter:markdown_to_html", + "//markdown_converter:markdown_to_html_wasm", ], dest = "src", )
--- a/seobeo/s_web.c Sun Jan 11 08:11:24 2026 -0800 +++ b/seobeo/s_web.c Mon Jan 12 09:11:58 2026 -0800 @@ -219,6 +219,7 @@ goto clean_up; } + Seobeo_Log(SEOBEO_DEBUG, "Serving Static Files\n"); // Serve static file const char *mime = "application/octet-stream"; if (strstr(file_path, ".html")) mime = "text/html; charset=utf-8";