Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 68 additions & 3 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ import {
useAppDefaults,
useAppFileHandling,
useClientService,
useAppsStore
useAppsStore,
useRoute,
useGetResourceContext
} from '@ownclouders/web-pkg'
import { Resource } from '@ownclouders/web-client/src'
import Reveal from 'reveal.js'
Expand All @@ -53,6 +55,8 @@ const { loadFolderForFileContext, currentFileContext, activeFiles } = useAppDefa
})
const { getUrlForResource, revokeUrl } = useAppFileHandling({ clientService })
const appsStore = useAppsStore()
const route = useRoute()
const { getResourceContext } = useGetResourceContext()

const isDarkMode = ref(themeStore.currentTheme.isDark)
const slideContainer = ref<HTMLElement>()
Expand All @@ -61,18 +65,24 @@ const mdTextarea = ref<HTMLElement>()
const mediaUrls = ref<string[]>([])
const isReadyToShow = ref<boolean>(false)
const presentationViewerRef = ref<HTMLElement>()
const customCssLink = ref(null)

const dataSeparator = '\r?\n---\r?\n'
const dataSeparatorVertical = '\r?\n--\r?\n'
const mdImageRegex = /!\[.*\]\((?!(?:http|data))(.*)\)/g
const headingSlideRegex = /^#+\s.*::slide:\s*([\w-]+)/m
const logoRegex = /(?<=logo:\s?)([^.]+\.[a-zA-Z]{3,4})/g
const templatePathRegex = /(?<=templatePath:\s?)(\S+)/g
const customCssFileRegex = /(?<=cssFile:\s?)(\S+)/g

let reveal: Reveal.Api
const awesoMd = RevealAwesoMD()
const baseUrl = `${window.location.origin}/assets/apps/${appId}`
const baseUrl = `${window.location.origin}/assets/apps/${appId}/templates`
awesoMd.setBaseUrl(baseUrl)
let loadTemplate = false
let customTemplate = false
let templatePathUrl = null
let customCssFile = null

const { url } = defineProps({
url: {
Expand Down Expand Up @@ -111,6 +121,18 @@ onMounted(async () => {
const logoUrl = await updateImageUrls(logoPath)
line = line.replace(`${logoPath}`, `${logoUrl}`)
}
// custom template
const templatePathMatches = line.matchAll(templatePathRegex)
for (const templatePathMatch of templatePathMatches) {
const templatePath = templatePathMatch[1].trim()
templatePathUrl = await updateTemplateUrl(templatePath)
awesoMd.setBaseUrl(templatePathUrl)
customTemplate = true
}
const customCssFileMatches = line.matchAll(customCssFileRegex)
for (const customCssFileMatch of customCssFileMatches) {
customCssFile = customCssFileMatch[1].trim()
}
parsedData.push(line)
}
unref(mdTextarea).textContent = parsedData.join('\n')
Expand All @@ -130,6 +152,7 @@ onMounted(async () => {
})

if (reveal.isReady()) {
loadCustomCss()
applyTemplateIfNeeded()
addCustomSlideNumber()
updateImageStructure()
Expand All @@ -146,7 +169,9 @@ onMounted(async () => {
})
onBeforeUnmount(() => {
presentationViewerRef.value.classList.remove('md-template')
customCssLink.value.remove()
loadTemplate = false
customTemplate = false
unref(mediaUrls).forEach((url) => {
revokeUrl(url)
})
Expand Down Expand Up @@ -242,6 +267,43 @@ function basename(path: string) {
return path.split('/').reverse()[0]
}

// custom templated related
function getTemplatePath(path: string) {
return unref(activeFiles).find((file: Resource) => file.name === path)
}
async function updateTemplateUrl(templatePath: string) {
if (['.', '/'].includes(templatePath)) {
const fileId = route.value.query.fileId as string
const space = await getResourceContext(fileId)
return `${window.location.origin}/dav/spaces/${space.space.id}`
}
let folder: Resource
if (templatePath.split('/').length > 1) {
folder = await getSubMediaFile(templatePath)
} else {
folder = getTemplatePath(templatePath)
}
if (!folder) {
return
}

const url = new URL(await getUrlForResource(unref(currentFileContext).space, folder))
return url.origin + url.pathname
}

function loadCustomCss() {
if (customTemplate) {
const cssFullUrl = templatePathUrl + '/' + customCssFile
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = cssFullUrl
link.id = 'reveal-custom-css'
const mainRevealContainer = document.getElementById('presentation-viewer-main')
mainRevealContainer.appendChild(link)
customCssLink.value = link
}
}

// TEMPLATE RELATED
function addCustomSlideNumber() {
const allSlides = reveal.getSlides()
Expand Down Expand Up @@ -400,7 +462,10 @@ function setFontColor() {
}
function applyTemplateIfNeeded() {
const [markdown, frontMatter] = separateFrontmatterAndMarkdown()
loadTemplate = !!(frontMatter.metadata?.slide || markdown.match(headingSlideRegex))
const hasSlideMetadata = frontMatter.metadata?.slide
const hasHeadingSlide = markdown.match(headingSlideRegex)
const hasTemplatePath = frontMatter.metadata?.templatePath
loadTemplate = !!(hasSlideMetadata || hasHeadingSlide) && !hasTemplatePath
if (loadTemplate) {
presentationViewerRef.value.classList.add('md-template')
setFontColor()
Expand Down
16 changes: 15 additions & 1 deletion tests/unit/App.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,21 @@ vi.mock('@ownclouders/web-pkg', () => ({
useConfigStore: vi.fn().mockImplementation(() => ({
serverUrl: 'https://localhost:9200'
})),
AppLoadingSpinner: vi.fn()
AppLoadingSpinner: vi.fn(),
useRoute: vi.fn().mockReturnValue({
value: {
query: {
fileId: 'test-file-id'
}
}
}),
useGetResourceContext: vi.fn().mockReturnValue({
getResourceContext: vi.fn().mockResolvedValue({
space: { id: 'test-space-id' },
resource: {},
path: '/test-path'
})
})
}))
// global mocks
const defaultFetchMock = vi.fn().mockImplementation(() =>
Expand Down
Loading