diff --git a/app/src/main/assets/katex/katex.html b/app/src/main/assets/katex/katex.html
new file mode 100644
index 00000000..ac5baaca
--- /dev/null
+++ b/app/src/main/assets/katex/katex.html
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/markdown/markdown.html b/app/src/main/assets/markdown/markdown.html
new file mode 100644
index 00000000..a4f2794b
--- /dev/null
+++ b/app/src/main/assets/markdown/markdown.html
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/chat/revolt/markdown/jbm/FallbackRenderer.kt b/app/src/main/java/chat/revolt/markdown/jbm/FallbackRenderer.kt
new file mode 100644
index 00000000..5d0e287a
--- /dev/null
+++ b/app/src/main/java/chat/revolt/markdown/jbm/FallbackRenderer.kt
@@ -0,0 +1,159 @@
+import android.annotation.SuppressLint
+import android.content.Intent
+import android.net.Uri
+import android.webkit.JavascriptInterface
+import android.webkit.WebChromeClient
+import android.webkit.WebResourceRequest
+import android.webkit.WebResourceResponse
+import android.webkit.WebSettings
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import androidx.browser.customtabs.CustomTabColorSchemeParams
+import androidx.browser.customtabs.CustomTabsIntent
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.webkit.WebViewAssetLoader
+import chat.revolt.activities.InviteActivity
+import chat.revolt.api.REVOLT_APP
+import chat.revolt.api.REVOLT_FILES
+import chat.revolt.api.RevoltAPI
+import chat.revolt.api.internals.ResourceLocations
+import chat.revolt.markdown.jbm.LocalJBMarkdownTreeState
+import chat.revolt.markdown.jbm.MentionResolver
+import chat.revolt.markdown.jbm.asHexString
+
+@SuppressLint("SetJavaScriptEnabled")
+@Composable
+fun FallbackRenderer(content: String, modifier: Modifier = Modifier) {
+ val colors = MaterialTheme.colorScheme
+ val mdState = LocalJBMarkdownTreeState.current
+
+ AndroidView(
+ modifier = modifier,
+ factory = { context ->
+ WebView(context).apply {
+ val assetLoader = WebViewAssetLoader.Builder()
+ .setDomain(Uri.parse(REVOLT_APP).host!!)
+ .addPathHandler(
+ "/_android_assets/",
+ WebViewAssetLoader.AssetsPathHandler(context)
+ )
+ .addPathHandler(
+ "/_android_res/",
+ WebViewAssetLoader.ResourcesPathHandler(context)
+ )
+ .build()
+
+ webChromeClient = object : WebChromeClient() {}
+ webViewClient = object : WebViewClient() {
+ override fun shouldInterceptRequest(
+ view: WebView?,
+ request: WebResourceRequest?
+ ): WebResourceResponse? {
+ return request?.let { assetLoader.shouldInterceptRequest(it.url) }
+ }
+
+ override fun shouldOverrideUrlLoading(
+ view: WebView?,
+ webResourceRequest: WebResourceRequest
+ ): Boolean {
+ // Capture clicks on invite links
+ if (webResourceRequest.url.host == "rvlt.gg" ||
+ (
+ webResourceRequest.url.host?.endsWith("revolt.chat") == true && webResourceRequest.url.path?.startsWith(
+ "/invite"
+ ) == true
+ )
+ ) {
+ val intent = Intent(
+ context,
+ InviteActivity::class.java
+ ).setAction(Intent.ACTION_VIEW)
+
+ intent.data = webResourceRequest.url
+ context.startActivity(intent)
+
+ return true
+ }
+
+ // Otherwise, open the link in the browser using androidx.browser
+ val customTab = CustomTabsIntent.Builder()
+ .setShowTitle(true)
+ .setDefaultColorSchemeParams(
+ CustomTabColorSchemeParams.Builder()
+ .setToolbarColor(colors.background.toArgb())
+ .build()
+ )
+ .build()
+ customTab.launchUrl(context, webResourceRequest.url)
+
+ // Prevent the WebView from navigating to the URL
+ return true
+ }
+ }
+
+ settings.apply {
+ javaScriptEnabled = true
+ setSupportZoom(false)
+ setSupportMultipleWindows(false)
+ isVerticalScrollBarEnabled = false
+ isHorizontalScrollBarEnabled = false
+ cacheMode = WebSettings.LOAD_NO_CACHE
+ }
+
+ addJavascriptInterface(
+ object {
+ @JavascriptInterface
+ fun getSource(): String {
+ return content
+ }
+
+ @JavascriptInterface
+ fun getForegroundColour(): String {
+ return colors.onBackground.asHexString()
+ }
+
+ @JavascriptInterface
+ fun getPrimaryColour(): String {
+ return colors.primary.asHexString()
+ }
+
+ @JavascriptInterface
+ fun getMentionBackgroundColour(): String {
+ return colors.primary.copy(alpha = 0.2f).asHexString()
+ }
+
+ @JavascriptInterface
+ fun getCustomEmoteUrl(emoteId: String): String {
+ return "$REVOLT_FILES/emojis/$emoteId/original"
+ }
+
+ @JavascriptInterface
+ fun resolveUserMention(userId: String): String {
+ return MentionResolver.resolveUser(userId, mdState.currentServer)
+ }
+
+ @JavascriptInterface
+ fun userAvatar(userId: String): String {
+ return ResourceLocations.userAvatarUrl(RevoltAPI.userCache[userId])
+ }
+
+ @JavascriptInterface
+ fun resolveChannelMention(channelId: String): String {
+ return MentionResolver.resolveChannel(channelId)
+ }
+ },
+ "Bridge"
+ )
+ setBackgroundColor(android.graphics.Color.TRANSPARENT)
+
+ loadUrl(
+ "$REVOLT_APP/_android_assets/markdown/markdown.html"
+ )
+ }
+ }
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/chat/revolt/markdown/jbm/JBMRenderer.kt b/app/src/main/java/chat/revolt/markdown/jbm/JBMRenderer.kt
index ff2a942f..87c169b9 100644
--- a/app/src/main/java/chat/revolt/markdown/jbm/JBMRenderer.kt
+++ b/app/src/main/java/chat/revolt/markdown/jbm/JBMRenderer.kt
@@ -1,5 +1,6 @@
package chat.revolt.markdown.jbm
+import FallbackRenderer
import android.content.Intent
import android.content.res.Configuration
import android.util.Log
@@ -22,6 +23,7 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.foundation.text.appendInlineContent
+import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@@ -89,7 +91,6 @@ import dev.snipme.highlights.model.ColorHighlight
import dev.snipme.highlights.model.SyntaxLanguage
import dev.snipme.highlights.model.SyntaxThemes
import kotlinx.coroutines.launch
-import logcat.logcat
import org.intellij.markdown.MarkdownElementTypes
import org.intellij.markdown.MarkdownTokenTypes
import org.intellij.markdown.ast.ASTNode
@@ -205,18 +206,11 @@ private fun annotateText(
)
)
- val member = state.currentServer?.let { serverId ->
- RevoltAPI.members.getMember(serverId, userId)
- }
- val mentionDisplay = member?.nickname
- ?: RevoltAPI.userCache[userId]?.username
- ?: "<@$userId>"
-
- appendInlineContent(JBMAnnotations.JBMBackgroundRoundingStart.tag)
+ append(" ")
appendInlineContent(JBMAnnotations.UserAvatar.tag, userId)
append(" ")
- append(mentionDisplay)
- appendInlineContent(JBMAnnotations.JBMBackgroundRoundingEnd.tag)
+ append(MentionResolver.resolveUser(userId, state.currentServer))
+ append(" ")
pop()
pop()
@@ -243,13 +237,7 @@ private fun annotateText(
)
)
- val channel = RevoltAPI.channelCache[channelId]
- val mentionDisplay = channel?.name?.let { name -> "#$name" }
- ?: "<#$channelId>"
-
- appendInlineContent(JBMAnnotations.JBMBackgroundRoundingStart.tag)
- append(mentionDisplay)
- appendInlineContent(JBMAnnotations.JBMBackgroundRoundingEnd.tag)
+ append(MentionResolver.resolveChannel(channelId))
pop()
pop()
@@ -950,12 +938,17 @@ private fun JBMBlock(node: ASTNode, modifier: Modifier, nestingCounter: Int = 0)
MarkdownElementTypes.HTML_BLOCK,
MarkdownElementTypes.LINK_DEFINITION,
MarkdownTokenTypes.WHITE_SPACE -> {
- CompositionLocalProvider(
- LocalTextStyle provides LocalTextStyle.current.copy(
- fontSize = LocalTextStyle.current.fontSize * state.fontSizeMultiplier
- )
- ) {
- JBMText(node, modifier)
+ // If the only child is a BLOCK_MATH we render it instead
+ if (node.children.size == 1 && node.children[0].type == GFMElementTypes.BLOCK_MATH) {
+ JBMBlock(node.children[0], modifier)
+ } else {
+ CompositionLocalProvider(
+ LocalTextStyle provides LocalTextStyle.current.copy(
+ fontSize = LocalTextStyle.current.fontSize * state.fontSizeMultiplier
+ )
+ ) {
+ JBMText(node, modifier)
+ }
}
}
@@ -1074,6 +1067,41 @@ private fun JBMBlock(node: ASTNode, modifier: Modifier, nestingCounter: Int = 0)
}
}
+ GFMElementTypes.BLOCK_MATH -> {
+ // No use using Katex in embedded because we don't want to
+ // create WebViews when embedded
+ if (!LocalJBMarkdownTreeState.current.embedded) {
+ val mathContent =
+ try {
+ node.getTextInNode(state.sourceText).toString().removeSurrounding("$$")
+ } catch (e: Exception) {
+ ""
+ }
+ KatexRenderer(mathContent, modifier)
+ }
+ }
+
+ GFMElementTypes.TABLE -> {
+ // Dito BLOCK_MATH
+ if (!LocalJBMarkdownTreeState.current.embedded) {
+ val tableContent = try {
+ node.getTextInNode(state.sourceText).toString()
+ } catch (e: Exception) {
+ ""
+ }
+
+ FallbackRenderer(tableContent, modifier)
+ }
+ }
+
+ MarkdownTokenTypes.HORIZONTAL_RULE -> {
+ HorizontalDivider(
+ color = colorScheme.onSurface,
+ thickness = 1.dp,
+ modifier = modifier.padding(vertical = 8.dp)
+ )
+ }
+
else -> {
Text(
text = buildAnnotatedString {
diff --git a/app/src/main/java/chat/revolt/markdown/jbm/KatexRenderer.kt b/app/src/main/java/chat/revolt/markdown/jbm/KatexRenderer.kt
new file mode 100644
index 00000000..0ee336db
--- /dev/null
+++ b/app/src/main/java/chat/revolt/markdown/jbm/KatexRenderer.kt
@@ -0,0 +1,134 @@
+package chat.revolt.markdown.jbm
+
+import android.annotation.SuppressLint
+import android.content.Intent
+import android.net.Uri
+import android.webkit.JavascriptInterface
+import android.webkit.WebChromeClient
+import android.webkit.WebResourceRequest
+import android.webkit.WebResourceResponse
+import android.webkit.WebSettings
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import androidx.browser.customtabs.CustomTabColorSchemeParams
+import androidx.browser.customtabs.CustomTabsIntent
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.webkit.WebViewAssetLoader
+import chat.revolt.activities.InviteActivity
+import chat.revolt.api.REVOLT_APP
+
+internal fun Color.asHexString(): String {
+ val argb = toArgb()
+ val alpha = (argb shr 24 and 0xff) / 255.0f
+ val red = argb shr 16 and 0xff
+ val green = argb shr 8 and 0xff
+ val blue = argb and 0xff
+ return String.format("#%02x%02x%02x%02x", red, green, blue, (alpha * 255).toInt())
+}
+
+@SuppressLint("SetJavaScriptEnabled")
+@Composable
+fun KatexRenderer(content: String, modifier: Modifier = Modifier) {
+ val colors = MaterialTheme.colorScheme
+
+ AndroidView(
+ modifier = modifier,
+ factory = { context ->
+ WebView(context).apply {
+ val assetLoader = WebViewAssetLoader.Builder()
+ .setDomain(Uri.parse(REVOLT_APP).host!!)
+ .addPathHandler(
+ "/_android_assets/",
+ WebViewAssetLoader.AssetsPathHandler(context)
+ )
+ .addPathHandler(
+ "/_android_res/",
+ WebViewAssetLoader.ResourcesPathHandler(context)
+ )
+ .build()
+
+ webChromeClient = object : WebChromeClient() {}
+ webViewClient = object : WebViewClient() {
+ override fun shouldInterceptRequest(
+ view: WebView?,
+ request: WebResourceRequest?
+ ): WebResourceResponse? {
+ return request?.let { assetLoader.shouldInterceptRequest(it.url) }
+ }
+
+ override fun shouldOverrideUrlLoading(
+ view: WebView?,
+ webResourceRequest: WebResourceRequest
+ ): Boolean {
+ // Capture clicks on invite links
+ if (webResourceRequest.url.host == "rvlt.gg" ||
+ (
+ webResourceRequest.url.host?.endsWith("revolt.chat") == true && webResourceRequest.url.path?.startsWith(
+ "/invite"
+ ) == true
+ )
+ ) {
+ val intent = Intent(
+ context,
+ InviteActivity::class.java
+ ).setAction(Intent.ACTION_VIEW)
+
+ intent.data = webResourceRequest.url
+ context.startActivity(intent)
+
+ return true
+ }
+
+ // Otherwise, open the link in the browser using androidx.browser
+ val customTab = CustomTabsIntent.Builder()
+ .setShowTitle(true)
+ .setDefaultColorSchemeParams(
+ CustomTabColorSchemeParams.Builder()
+ .setToolbarColor(colors.background.toArgb())
+ .build()
+ )
+ .build()
+ customTab.launchUrl(context, webResourceRequest.url)
+
+ // Prevent the WebView from navigating to the URL
+ return true
+ }
+ }
+
+ settings.apply {
+ javaScriptEnabled = true
+ setSupportZoom(false)
+ setSupportMultipleWindows(false)
+ isVerticalScrollBarEnabled = false
+ isHorizontalScrollBarEnabled = false
+ cacheMode = WebSettings.LOAD_NO_CACHE
+ }
+
+ addJavascriptInterface(
+ object {
+ @JavascriptInterface
+ fun getSource(): String {
+ return content
+ }
+
+ @JavascriptInterface
+ fun getForegroundColour(): String {
+ return colors.onBackground.asHexString()
+ }
+ },
+ "Bridge"
+ )
+ setBackgroundColor(android.graphics.Color.TRANSPARENT)
+
+ loadUrl(
+ "$REVOLT_APP/_android_assets/katex/katex.html"
+ )
+ }
+ }
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/chat/revolt/markdown/jbm/MentionResolver.kt b/app/src/main/java/chat/revolt/markdown/jbm/MentionResolver.kt
new file mode 100644
index 00000000..1874863a
--- /dev/null
+++ b/app/src/main/java/chat/revolt/markdown/jbm/MentionResolver.kt
@@ -0,0 +1,32 @@
+package chat.revolt.markdown.jbm
+
+import chat.revolt.api.RevoltAPI
+
+object MentionResolver {
+ /**
+ * Resolves a user mention to its fancy representation.
+ * Note that this uses the new format without a leading @ unless the user is not found.
+ *
+ * @param userId The user ID to resolve.
+ * @param serverId The server ID to resolve the user in.
+ * @return The resolved user mention.
+ */
+ fun resolveUser(userId: String, serverId: String? = null): String {
+ val maybeMember = serverId?.let { RevoltAPI.members.getMember(serverId, userId) }
+ return maybeMember?.nickname
+ ?: RevoltAPI.userCache[userId]?.username
+ ?: "<@$userId>"
+ }
+
+ /**
+ * Resolves a channel mention to its fancy representation.
+ *
+ * @param channelId The channel ID to resolve.
+ * @param serverId The server ID to resolve the channel in.
+ * @return The resolved channel mention.
+ */
+ fun resolveChannel(channelId: String): String {
+ val channel = RevoltAPI.channelCache[channelId]
+ return channel?.name?.let { name -> "#$name" } ?: "<#$channelId>"
+ }
+}
\ No newline at end of file
diff --git a/scripts/download_deps.ts b/scripts/download_deps.ts
index bba8c760..6476353b 100644
--- a/scripts/download_deps.ts
+++ b/scripts/download_deps.ts
@@ -46,20 +46,268 @@ const deps = [
url: "https://cdn.jsdelivr.net/npm/katex@0.16.19/dist/katex.min.js",
},
{
- file: "micromark.bundle.js",
- url: "https://esm.sh/v135/micromark@4.0.1/es2022/micromark.bundle.mjs",
+ file: "fonts/KaTeX_AMS-Regular.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_AMS-Regular.ttf",
},
+ {
+ file: "fonts/KaTeX_AMS-Regular.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_AMS-Regular.woff",
+ },
+ {
+ file: "fonts/KaTeX_AMS-Regular.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_AMS-Regular.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Caligraphic-Bold.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Caligraphic-Bold.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Caligraphic-Bold.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Caligraphic-Bold.woff",
+ },
+ {
+ file: "fonts/KaTeX_Caligraphic-Bold.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Caligraphic-Bold.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Caligraphic-Regular.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Caligraphic-Regular.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Caligraphic-Regular.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Caligraphic-Regular.woff",
+ },
+ {
+ file: "fonts/KaTeX_Caligraphic-Regular.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Caligraphic-Regular.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Fraktur-Bold.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Fraktur-Bold.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Fraktur-Bold.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Fraktur-Bold.woff",
+ },
+ {
+ file: "fonts/KaTeX_Fraktur-Bold.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Fraktur-Bold.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Fraktur-Regular.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Fraktur-Regular.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Fraktur-Regular.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Fraktur-Regular.woff",
+ },
+ {
+ file: "fonts/KaTeX_Fraktur-Regular.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Fraktur-Regular.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Main-Bold.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Main-Bold.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Main-Bold.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Main-Bold.woff",
+ },
+ {
+ file: "fonts/KaTeX_Main-Bold.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Main-Bold.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Main-BoldItalic.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Main-BoldItalic.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Main-BoldItalic.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Main-BoldItalic.woff",
+ },
+ {
+ file: "fonts/KaTeX_Main-BoldItalic.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Main-BoldItalic.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Main-Italic.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Main-Italic.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Main-Italic.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Main-Italic.woff",
+ },
+ {
+ file: "fonts/KaTeX_Main-Italic.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Main-Italic.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Main-Regular.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Main-Regular.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Main-Regular.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Main-Regular.woff",
+ },
+ {
+ file: "fonts/KaTeX_Main-Regular.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Main-Regular.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Math-BoldItalic.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Math-BoldItalic.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Math-BoldItalic.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Math-BoldItalic.woff",
+ },
+ {
+ file: "fonts/KaTeX_Math-BoldItalic.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Math-BoldItalic.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Math-Italic.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Math-Italic.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Math-Italic.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Math-Italic.woff",
+ },
+ {
+ file: "fonts/KaTeX_Math-Italic.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Math-Italic.woff2",
+ },
+ {
+ file: "fonts/KaTeX_SansSerif-Bold.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_SansSerif-Bold.ttf",
+ },
+ {
+ file: "fonts/KaTeX_SansSerif-Bold.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_SansSerif-Bold.woff",
+ },
+ {
+ file: "fonts/KaTeX_SansSerif-Bold.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_SansSerif-Bold.woff2",
+ },
+ {
+ file: "fonts/KaTeX_SansSerif-Italic.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_SansSerif-Italic.ttf",
+ },
+ {
+ file: "fonts/KaTeX_SansSerif-Italic.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_SansSerif-Italic.woff",
+ },
+ {
+ file: "fonts/KaTeX_SansSerif-Italic.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_SansSerif-Italic.woff2",
+ },
+ {
+ file: "fonts/KaTeX_SansSerif-Regular.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_SansSerif-Regular.ttf",
+ },
+ {
+ file: "fonts/KaTeX_SansSerif-Regular.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_SansSerif-Regular.woff",
+ },
+ {
+ file: "fonts/KaTeX_SansSerif-Regular.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_SansSerif-Regular.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Script-Regular.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Script-Regular.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Script-Regular.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Script-Regular.woff",
+ },
+ {
+ file: "fonts/KaTeX_Script-Regular.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Script-Regular.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Size1-Regular.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Size1-Regular.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Size1-Regular.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Size1-Regular.woff",
+ },
+ {
+ file: "fonts/KaTeX_Size1-Regular.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Size1-Regular.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Size2-Regular.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Size2-Regular.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Size2-Regular.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Size2-Regular.woff",
+ },
+ {
+ file: "fonts/KaTeX_Size2-Regular.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Size2-Regular.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Size3-Regular.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Size3-Regular.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Size3-Regular.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Size3-Regular.woff",
+ },
+ {
+ file: "fonts/KaTeX_Size3-Regular.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Size3-Regular.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Size4-Regular.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Size4-Regular.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Size4-Regular.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Size4-Regular.woff",
+ },
+ {
+ file: "fonts/KaTeX_Size4-Regular.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Size4-Regular.woff2",
+ },
+ {
+ file: "fonts/KaTeX_Typewriter-Regular.ttf",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Typewriter-Regular.ttf",
+ },
+ {
+ file: "fonts/KaTeX_Typewriter-Regular.woff",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Typewriter-Regular.woff",
+ },
+ {
+ file: "fonts/KaTeX_Typewriter-Regular.woff2",
+ url: "https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/fonts/KaTeX_Typewriter-Regular.woff2",
+ },
+ {
+ file: "micromark.bundle.js",
+ url: "https://esm.sh/v135/micromark@3.2.0/es2022/micromark.bundle.mjs",
+ },
+ {
+ file: "micromark-gfm.bundle.js",
+ url: "https://esm.sh/v135/micromark-extension-gfm@3.0.0/es2022/micromark-extension-gfm.bundle.mjs",
+ }
]
-console.log("Will download the following files:")
for (const dep of deps) {
console.log(`- ${dep.file} from ${dep.url}`)
}
+
+console.log("Will download the above files.")
if (!confirm("Continue?")) {
console.log("Aborted.")
Deno.exit(0)
}
+const fontsFolder = resolve(outputFolder, "fonts")
+Deno.mkdirSync(fontsFolder, { recursive: true })
+
for (const dep of deps) {
const response = await fetch(dep.url)
const data = await response.arrayBuffer()