Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: update ocis images directly in markdown content #61

Merged
merged 5 commits into from
Jul 16, 2024
Merged
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
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Use ocis images from same directory level (https://github.com/JankariTech/web-app-presentation-viewer/pull/48)
- Loading spinner until presentation is ready (https://github.com/JankariTech/web-app-presentation-viewer/pull/61)
- Load ocis images from the sub directory level (https://github.com/JankariTech/web-app-presentation-viewer/pull/60)
- Use ocis images from same directory level (https://github.com/JankariTech/web-app-presentation-viewer/pull/48)

### Fixed

### Changed

- Parse and update local image urls directly in the markdown content (https://github.com/JankariTech/web-app-presentation-viewer/pull/61)

### Removed

## [1.0.0] - 2024-05-07
Expand Down
83 changes: 41 additions & 42 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
<template>
<div
id="presentation-viewer-main"
class="presentation-viewer oc-flex"
class="presentation-viewer"
:class="{ 'dark-mode': isDarkMode }"
>
<AppLoadingSpinner v-if="!isReadyToShow" />
<div ref="revealContainer" class="reveal">
<div id="slideContainer" ref="slideContainer" class="slides">
<section
:data-markdown="url"
data-markdown
:data-separator="dataSeparator"
:data-separator-vertical="dataSeparatorVertical"
></section>
>
<textarea ref="mdTextarea" data-template />
</section>
</div>
</div>
</div>
Expand All @@ -19,12 +22,12 @@
<script setup lang="ts">
import { computed, onMounted, onBeforeUnmount, ref, unref, watch } from 'vue'
import {
AppLoadingSpinner,
useThemeStore,
useAppDefaults,
useAppFileHandling,
useClientService,
useAppsStore,
useConfigStore
useAppsStore
} from '@ownclouders/web-pkg'
import { Resource } from '@ownclouders/web-client/src'
import Reveal from 'reveal.js'
Expand All @@ -46,20 +49,21 @@ const { loadFolderForFileContext, currentFileContext, activeFiles } = useAppDefa
})
const { getUrlForResource, revokeUrl } = useAppFileHandling({ clientService })
const appsStore = useAppsStore()
const { serverUrl } = useConfigStore()

const isDarkMode = ref(themeStore.currentTheme.isDark)
const slideContainer = ref<HTMLElement>()
const revealContainer = ref<HTMLElement>()
const mdTextarea = ref<HTMLElement>()
const mediaUrls = ref<string[]>([])
const isReadyToShow = ref<boolean>(false)

const mediaBasePath = `${serverUrl}local/`
const dataSeparator = '\r?\n---\r?\n'
const dataSeparatorVertical = '\r?\n--\r?\n'
const mdImageRegex = /!\[.*\]\((?!(?:http|data))(.*)\)/g

let reveal: Reveal.Api

defineProps({
const { url } = defineProps({
url: {
type: String,
required: true
Expand All @@ -77,6 +81,24 @@ watch(
onMounted(async () => {
await loadFolderForFileContext(unref(currentFileContext))

// fetch the markdown file
// build the local image urls
await fetch(unref(url))
.then((res) => res.text())
.then(async (data) => {
const parsedData = []
for (let line of data.split('\n')) {
const matches = line.matchAll(mdImageRegex)
for (const match of matches) {
const imgPath = match[1]
const imageUrl = await updateImageUrls(imgPath)
line = line.replace(`(${imgPath})`, `(${imageUrl})`)
}
parsedData.push(line)
}
unref(mdTextarea).textContent = parsedData.join('\n')
})

reveal = new Reveal(unref(revealContainer), {
plugins: [RevealMarkdown, RevealHighlight]
})
Expand All @@ -86,20 +108,10 @@ onMounted(async () => {
progress: true,
history: true,
center: true,
controlsLayout: 'edges',
markdown: {
baseUrl: mediaBasePath
}
controlsLayout: 'edges'
})

reveal.on('ready', async () => {
if (unref(slideContainer) === undefined) {
return
}
const imgElements = (unref(slideContainer) as HTMLElement).getElementsByTagName('img')
const localImgElements = filterLocalImgElements(imgElements)
await updateImageUrls(localImgElements)
})
isReadyToShow.value = true
})
onBeforeUnmount(() => {
unref(mediaUrls).forEach((url) => {
Expand All @@ -125,29 +137,16 @@ const mediaFiles = computed<Resource[]>(() => {
})

// METHODS
function filterLocalImgElements(
imgElements: HTMLCollectionOf<HTMLImageElement>
): HTMLImageElement[] {
const localImgElements: HTMLImageElement[] = []
for (const el of imgElements) {
if (el.src.startsWith(mediaBasePath)) {
localImgElements.push(el)
}
}
return localImgElements
}
async function updateImageUrls(localImgElements: HTMLImageElement[]) {
for (const el of localImgElements) {
// trim 'mediaBasePath'
// remove leading '.' and '/'
const srcPath = el.src.replace(mediaBasePath, '').replace(/$\.\//, '').replace(/$\//, '')

const blobUrl = await parseImageUrl(srcPath)
if (blobUrl) {
el.src = blobUrl
mediaUrls.value.push(blobUrl)
}
async function updateImageUrls(localImagePath: string) {
// remove leading './' or '/'
const srcPath = localImagePath.replace(/^\.\//, '').replace(/^\//, '')

const blobUrl = await parseImageUrl(srcPath)
if (blobUrl) {
mediaUrls.value.push(blobUrl)
return blobUrl
}
return localImagePath
}
async function parseImageUrl(name: string) {
let file: Resource
Expand Down