You've already forked AstralRinth
add spark blog post
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
<script setup lang="ts">
|
||||
import { type Component, computed } from 'vue'
|
||||
|
||||
import SparkLiveWidget from './SparkLiveWidget.vue'
|
||||
import SparkLiveWidgetEmbed from './SparkLiveWidgetEmbed.vue'
|
||||
|
||||
const ARTICLE_WIDGETS: Record<string, Component> = {
|
||||
'spark-live-widget': SparkLiveWidget,
|
||||
'spark-live-widget-embed': SparkLiveWidgetEmbed,
|
||||
}
|
||||
|
||||
type ArticleBodyPart = { type: 'html'; content: string } | { type: 'widget'; id: string }
|
||||
|
||||
function parseArticleHtml(html: string): ArticleBodyPart[] {
|
||||
const widgetIds = Object.keys(ARTICLE_WIDGETS)
|
||||
if (widgetIds.length === 0) {
|
||||
return [{ type: 'html', content: html }]
|
||||
}
|
||||
|
||||
const pattern = new RegExp(`<div id="(${widgetIds.join('|')})"></div>`, 'g')
|
||||
const parts: ArticleBodyPart[] = []
|
||||
let lastIndex = 0
|
||||
let match: RegExpExecArray | null
|
||||
|
||||
while ((match = pattern.exec(html)) !== null) {
|
||||
if (match.index > lastIndex) {
|
||||
parts.push({ type: 'html', content: html.slice(lastIndex, match.index) })
|
||||
}
|
||||
parts.push({ type: 'widget', id: match[1] })
|
||||
lastIndex = pattern.lastIndex
|
||||
}
|
||||
|
||||
if (lastIndex < html.length) {
|
||||
parts.push({ type: 'html', content: html.slice(lastIndex) })
|
||||
}
|
||||
|
||||
return parts.length > 0 ? parts : [{ type: 'html', content: html }]
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
html: string
|
||||
}>()
|
||||
|
||||
const parts = computed(() => parseArticleHtml(props.html))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="markdown-body">
|
||||
<template v-for="(part, index) in parts" :key="index">
|
||||
<div v-if="part.type === 'html'" v-html="part.content" />
|
||||
<component :is="ARTICLE_WIDGETS[part.id]" v-else />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,63 @@
|
||||
<script setup lang="ts">
|
||||
import { VideoIcon } from '@modrinth/assets'
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
embed?: boolean
|
||||
}>(),
|
||||
{
|
||||
embed: false,
|
||||
},
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="rounded-2xl border border-solid border-surface-4 bg-surface-3 overflow-hidden">
|
||||
<div class="p-4 flex flex-col gap-3">
|
||||
<div class="flex items-center gap-2">
|
||||
<VideoIcon class="size-6 text-brand" />
|
||||
<span class="text-contrast font-medium">
|
||||
We're hosting a live chat with Spark later today to answer all of your questions!
|
||||
</span>
|
||||
</div>
|
||||
<span>
|
||||
Ask questions for us to answer in our
|
||||
<a
|
||||
href="https://discord.modrinth.com"
|
||||
target="_blank"
|
||||
class="text-brand font-semibold hover:underline"
|
||||
>Discord server</a
|
||||
>.
|
||||
</span>
|
||||
<span
|
||||
>Tune in live on June 15, 11am PST / 2pm EST / 7pm BST / 8pm CEST over on our
|
||||
<a
|
||||
href="https://www.youtube.com/live/p1Dg-fud0TQ"
|
||||
target="_blank"
|
||||
class="text-brand font-semibold hover:underline"
|
||||
>YouTube channel</a
|
||||
>.</span
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
v-if="embed"
|
||||
style="left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%"
|
||||
>
|
||||
<iframe
|
||||
src="https://www.youtube.com/embed/p1Dg-fud0TQ"
|
||||
style="top: 0; left: 0; width: 100%; height: 100%; position: absolute; border: 0"
|
||||
allowfullscreen
|
||||
scrolling="no"
|
||||
allow="
|
||||
accelerometer *;
|
||||
clipboard-write *;
|
||||
encrypted-media *;
|
||||
gyroscope *;
|
||||
picture-in-picture *;
|
||||
web-share *;
|
||||
"
|
||||
referrerpolicy="strict-origin"
|
||||
></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import SparkLiveWidget from './SparkLiveWidget.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SparkLiveWidget embed />
|
||||
</template>
|
||||
@@ -1,3 +1,5 @@
|
||||
export { default as ArticleBody } from './ArticleBody.vue'
|
||||
export { default as ContentListPanel } from './ContentListPanel.vue'
|
||||
export type { Article as NewsArticle } from './NewsArticleCard.vue'
|
||||
export { default as NewsArticleCard } from './NewsArticleCard.vue'
|
||||
export { default as SparkLiveWidget } from './SparkLiveWidget.vue'
|
||||
|
||||
Reference in New Issue
Block a user