From 2f0a3efde7eed1466c8589b72c0365c5311dca33 Mon Sep 17 00:00:00 2001 From: benoit74 Date: Mon, 21 Oct 2024 08:33:32 +0000 Subject: [PATCH] Move from directive to service for simplicity --- zimui/src/directives/mathjax.ts | 100 ------------------- zimui/src/main.ts | 2 - zimui/src/services/__tests__/mathjax.spec.ts | 14 +++ zimui/src/services/mathjax.ts | 79 +++++++++++++++ zimui/src/stores/main.ts | 3 + zimui/src/views/HomeView.vue | 1 - 6 files changed, 96 insertions(+), 103 deletions(-) delete mode 100644 zimui/src/directives/mathjax.ts create mode 100644 zimui/src/services/__tests__/mathjax.spec.ts create mode 100644 zimui/src/services/mathjax.ts diff --git a/zimui/src/directives/mathjax.ts b/zimui/src/directives/mathjax.ts deleted file mode 100644 index 8727940..0000000 --- a/zimui/src/directives/mathjax.ts +++ /dev/null @@ -1,100 +0,0 @@ -/* -Directive to handle DOM manipulation to add/remove MathJax everytime the page change - -This is a bit hackhish but the only reliable solution found so far, and probably the -most robust one. - -The dynamic behavior of removing / adding back MathJax is wanted/necessary because we -need to dynamically set the PageIndex macro to dynamically display proper figures -/ equations / ... numbering. - -This directive MUST be used only once in the whole Vue.JS application. - -MathJax settings are an adaptation of libretexts.org settings, for MathJax 3 (including -extensions now removed or not yet supported or included by default). -*/ -import type { DirectiveBinding } from 'vue' - -let front: string | undefined = undefined - -const frontFromTitle = function (title: string): string { - // Computes front value from page title. - // E.g. if page title is `1.2: The Scientific Method` then front is `1.2.` - let front: string = '' - if (title.includes(':')) { - front = title.split(':')[0] - if (front.includes('.')) { - const parts: string[] = front.split('.') - front = parts.map((int) => (int.includes('0') ? parseInt(int, 10) : int)).join('.') - } - front += '.' - } - return front -} - -const removeMathJax = function () { - const script = document.getElementById('mathjax-script') - if (script) script.remove() - if (window.MathJax) delete window.MathJax -} - -const addMathJax = function (front: string) { - window.MathJax = { - section: front, - tex: { - tags: 'all', - macros: { - PageIndex: ['{' + front + '#1}'.toString(), 1] - }, - autoload: { - color: [], - colorv2: ['color'] - }, - packages: { '[+]': ['noerrors', 'mhchem', 'tagFormat', 'color', 'cancel'] } - }, - loader: { - load: ['[tex]/noerrors', '[tex]/mhchem', '[tex]/tagFormat', '[tex]/colorv2', '[tex]/cancel'] - }, - svg: { - scale: 0.85 - }, - options: { - menuOptions: { - settings: { - zoom: 'Double-Click', - zscale: '150%' - } - } - } - } - const script = document.createElement('script', { - id: 'mathjax-script' - } as ElementCreationOptions) - script.src = './mathjax/es5/tex-svg.js' - script.async = false - document.head.appendChild(script) -} - -const vMathJax = { - mounted(el: HTMLElement, binding: DirectiveBinding) { - front = frontFromTitle(binding.value.title) - removeMathJax() // "just-in-case" - addMathJax(front) - }, - updated(el: HTMLElement, binding: DirectiveBinding) { - // Reload MathJax only if title has changed (allow to debounce update which might be - // called multiple times) - const new_front = frontFromTitle(binding.value.title) - if (new_front == front) { - return - } - front = new_front - removeMathJax() - addMathJax(front) - }, - unmounted() { - removeMathJax() - } -} - -export default vMathJax diff --git a/zimui/src/main.ts b/zimui/src/main.ts index e598036..5531a32 100644 --- a/zimui/src/main.ts +++ b/zimui/src/main.ts @@ -8,7 +8,6 @@ import router from './router' import loadVuetify from './plugins/vuetify' import ResizeObserver from 'resize-observer-polyfill' -import vMathJax from './directives/mathjax' if (typeof window.ResizeObserver === 'undefined') { console.debug('Polyfilling ResizeObserver') @@ -21,7 +20,6 @@ loadVuetify() app.use(createPinia()) app.use(vuetify) app.use(router) - app.directive('mathjax', vMathJax) app.mount('#app') }) .catch((error) => { diff --git a/zimui/src/services/__tests__/mathjax.spec.ts b/zimui/src/services/__tests__/mathjax.spec.ts new file mode 100644 index 0000000..f1ea888 --- /dev/null +++ b/zimui/src/services/__tests__/mathjax.spec.ts @@ -0,0 +1,14 @@ +import { describe, it, expect } from 'vitest' +import mathjaxService from '../mathjax' + +describe('MathJaxService', () => { + it('computes front 1.2. properly', () => { + expect(mathjaxService.frontFromTitle('1.2: The Scientific Method')).toBe('1.2.') + }) + it('computes front 1.3. properly', () => { + expect(mathjaxService.frontFromTitle('1.3: The Foo Method')).toBe('1.3.') + }) + it('computes front 1. properly', () => { + expect(mathjaxService.frontFromTitle('1: The Title Method')).toBe('1.') + }) +}) diff --git a/zimui/src/services/mathjax.ts b/zimui/src/services/mathjax.ts new file mode 100644 index 0000000..91db288 --- /dev/null +++ b/zimui/src/services/mathjax.ts @@ -0,0 +1,79 @@ +/* +Service to handle DOM manipulation to add/remove MathJax everytime needed. + +This is a bit hackhish to remove and and back MathJax, but it is the only reliable +solution found so far, and probably the most robust one. + +The dynamic behavior of removing / adding back MathJax is wanted/necessary because we +need to dynamically set the PageIndex macro to dynamically display proper figures +/ equations / ... numbering. + +MathJax settings are an adaptation of libretexts.org settings, for MathJax 3 (including +extensions now removed or not yet supported or included by default). +*/ + +class MathJaxService { + front: string | undefined = undefined + + frontFromTitle(title: string): string { + // Computes front value from page title. + // E.g. if page title is `1.2: The Scientific Method` then front is `1.2.` + let front: string = '' + if (title.includes(':')) { + front = title.split(':')[0] + if (front.includes('.')) { + const parts: string[] = front.split('.') + front = parts.map((int) => (int.includes('0') ? parseInt(int, 10) : int)).join('.') + } + front += '.' + } + return front + } + + removeMathJax() { + const script = document.getElementById('mathjax-script') + if (script) script.remove() + if (window.MathJax) delete window.MathJax + } + + addMathJax(front: string) { + window.MathJax = { + section: front, + tex: { + tags: 'all', + macros: { + PageIndex: ['{' + front + '#1}'.toString(), 1] + }, + autoload: { + color: [], + colorv2: ['color'] + }, + packages: { '[+]': ['noerrors', 'mhchem', 'tagFormat', 'color', 'cancel'] } + }, + loader: { + load: ['[tex]/noerrors', '[tex]/mhchem', '[tex]/tagFormat', '[tex]/colorv2', '[tex]/cancel'] + }, + svg: { + scale: 0.85 + }, + options: { + menuOptions: { + settings: { + zoom: 'Double-Click', + zscale: '150%' + } + } + } + } + const script = document.createElement('script', { + id: 'mathjax-script' + } as ElementCreationOptions) + script.src = './mathjax/es5/tex-svg.js' + document.head.appendChild(script) + } +} + +const mathjaxService = new MathJaxService() +Object.freeze(mathjaxService) + +export default mathjaxService diff --git a/zimui/src/stores/main.ts b/zimui/src/stores/main.ts index 286de30..4f0ae51 100644 --- a/zimui/src/stores/main.ts +++ b/zimui/src/stores/main.ts @@ -1,6 +1,7 @@ import { defineStore } from 'pinia' import axios, { AxiosError } from 'axios' import type { PageContent, Shared, SharedPage } from '@/types/shared' +import mathjaxService from '@/services/mathjax' export type RootState = { shared: Shared | null @@ -56,6 +57,8 @@ export const useMainStore = defineStore('main', { (response) => { this.isLoading = false this.pageContent = response.data as PageContent + mathjaxService.removeMathJax() + mathjaxService.addMathJax(mathjaxService.frontFromTitle(page.title)) }, (error) => { this.isLoading = false diff --git a/zimui/src/views/HomeView.vue b/zimui/src/views/HomeView.vue index 68fa300..358864c 100644 --- a/zimui/src/views/HomeView.vue +++ b/zimui/src/views/HomeView.vue @@ -50,7 +50,6 @@ watch( class="mt-content-container" v-if="main.pageContent" v-html="main.pageContent.htmlBody" - v-mathjax="page" >
Page not found