Skip to content

Commit

Permalink
refactor: update ocis images directly in markdown content (#61)
Browse files Browse the repository at this point in the history
* refactor: parse and set local image url in markdown

* refactor: add loading spinner

* fix: uploaded image url treated as local

* docs: add changelog entry

* docs: update comment line
  • Loading branch information
saw-jan authored Jul 16, 2024
1 parent bff366c commit 6f4d5e5
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 43 deletions.
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

0 comments on commit 6f4d5e5

Please sign in to comment.