@simple-reporting/base 1.0.21 → 1.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dev/package.json +1 -1
- package/dev/src/assets/scss/general.scss +1 -0
- package/dev/src/assets/scss/pdf.scss +13 -0
- package/dev/src/assets/scss/placeholders.scss +48 -0
- package/dev/src/entries/pdf.ts +14 -1
- package/dev/srl.config.json +106 -0
- package/livingdocs/010.Titles/010.title-h1/scss/general.scss +12 -0
- package/livingdocs/010.Titles/020.title-h2/scss/general.scss +12 -1
- package/livingdocs/010.Titles/030.title-h3/scss/general.scss +0 -1
- package/livingdocs/010.Titles/040.title-h4/scss/general.scss +0 -1
- package/livingdocs/010.Titles/050.title-h5/scss/general.scss +0 -1
- package/livingdocs/010.Titles/060.title-h6/scss/general.scss +0 -1
- package/livingdocs/020.Text/010.lead/scss/general.scss +0 -1
- package/livingdocs/020.Text/020.paragraph/scss/general.scss +0 -1
- package/livingdocs/020.Text/040.link/scss/general.scss +0 -1
- package/livingdocs/020.Text/050.quote/scss/general.scss +0 -4
- package/livingdocs/020.Text/060.quote-with-portrait/scss/general.scss +4 -1
- package/livingdocs/020.Text/070.footnote-container/scss/general.scss +1 -2
- package/livingdocs/020.Text/080.footnote-item/scss/general.scss +0 -8
- package/livingdocs/020.Text/080.footnote-item/scss/pdf.scss +8 -1
- package/livingdocs/020.Text/080.footnote-item/scss/web.scss +8 -1
- package/livingdocs/030.Lists/010.unordered-list/scss/general.scss +3 -3
- package/livingdocs/030.Lists/010.unordered-list/scss/pdf.scss +8 -0
- package/livingdocs/030.Lists/010.unordered-list/scss/web.scss +2 -0
- package/livingdocs/030.Lists/010.unordered-list/unordered-list.html +1 -1
- package/livingdocs/030.Lists/020.ordered-list/scss/general.scss +2 -5
- package/livingdocs/030.Lists/030.alphanumeric-list/scss/general.scss +2 -5
- package/livingdocs/030.Lists/040.list-item/scss/general.scss +7 -0
- package/livingdocs/030.Lists/040.list-item/scss/web.scss +13 -0
- package/livingdocs/040.Media/010.table/scss/general.scss +18 -39
- package/livingdocs/040.Media/010.table/scss/pdf.scss +20 -0
- package/livingdocs/040.Media/020.image/scss/general.scss +0 -4
- package/livingdocs/080.CV/010.cv/cv.html +34 -32
- package/livingdocs/080.CV/010.cv/scss/app.scss +1 -0
- package/livingdocs/080.CV/010.cv/scss/editor.scss +1 -0
- package/livingdocs/080.CV/010.cv/scss/general.scss +15 -0
- package/livingdocs/080.CV/010.cv/scss/pdf.scss +14 -0
- package/livingdocs/080.CV/010.cv/scss/web.scss +15 -0
- package/livingdocs/080.CV/010.cv/scss/word.scss +0 -0
- package/livingdocs/080.CV/010.cv/scss/xbrl.scss +1 -0
- package/livingdocs/080.CV/020.cv-time-span/cv-time-span.html +14 -12
- package/livingdocs/080.CV/020.cv-time-span/scss/app.scss +1 -0
- package/livingdocs/080.CV/020.cv-time-span/scss/editor.scss +1 -0
- package/livingdocs/080.CV/020.cv-time-span/scss/general.scss +10 -0
- package/livingdocs/080.CV/020.cv-time-span/scss/pdf.scss +10 -0
- package/livingdocs/080.CV/020.cv-time-span/scss/web.scss +10 -0
- package/livingdocs/080.CV/020.cv-time-span/scss/word.scss +0 -0
- package/livingdocs/080.CV/020.cv-time-span/scss/xbrl.scss +1 -0
- package/livingdocs/090.Signatures/020.signature-item/scss/general.scss +1 -0
- package/livingdocs/100.Misc/010.anchor/anchor.html +1 -1
- package/livingdocs/100.Misc/020.accordion/accordion.html +7 -5
- package/livingdocs/110.PDF/050.pdf-chapter-navigation-container/pdf-chapter-navigation.html +1 -1
- package/livingdocs/110.PDF/050.pdf-chapter-navigation-container/scss/editor.scss +4 -0
- package/livingdocs/110.PDF/050.pdf-chapter-navigation-container/scss/general.scss +9 -1
- package/livingdocs/110.PDF/050.pdf-chapter-navigation-container/scss/pdf.scss +0 -9
- package/livingdocs/110.PDF/060.pdf-chapter-navigation-item/pdf-chapter-navigation-item.html +3 -2
- package/livingdocs/110.PDF/060.pdf-chapter-navigation-item/scss/general.scss +14 -1
- package/livingdocs/110.PDF/060.pdf-chapter-navigation-item/scss/pdf.scss +1 -14
- package/livingdocs/110.PDF/070.pdf-cover/ld-conf.json +3 -0
- package/livingdocs/110.PDF/070.pdf-cover/properties.json +19 -0
- package/livingdocs/110.PDF/070.pdf-cover/scss/editor.scss +7 -0
- package/livingdocs/110.PDF/070.pdf-cover/scss/general.scss +22 -0
- package/livingdocs/110.PDF/070.pdf-cover/scss/pdf.scss +22 -0
- package/livingdocs/110.PDF/070.pdf-cover/scss/web.scss +1 -0
- package/livingdocs/110.PDF/070.pdf-cover/scss/word.scss +0 -0
- package/livingdocs/110.PDF/070.pdf-cover/scss/xbrl.scss +1 -0
- package/livingdocs/110.PDF/080.pdf-toc-page/pdf-toc-page.html +1 -1
- package/livingdocs/110.PDF/080.pdf-toc-page/scss/editor.scss +35 -0
- package/livingdocs/110.PDF/080.pdf-toc-page/scss/general.scss +5 -0
- package/livingdocs/110.PDF/080.pdf-toc-page/scss/pdf.scss +20 -0
- package/livingdocs/110.PDF/080.pdf-toc-page/scss/web.scss +1 -0
- package/livingdocs/110.PDF/080.pdf-toc-page/scss/word.scss +0 -0
- package/livingdocs/110.PDF/080.pdf-toc-page/scss/xbrl.scss +1 -0
- package/livingdocs/110.PDF/090.pdf-toc-item-title/pdf-toc-item-title.html +1 -1
- package/livingdocs/110.PDF/090.pdf-toc-item-title/scss/editor.scss +3 -0
- package/livingdocs/110.PDF/090.pdf-toc-item-title/scss/general.scss +5 -0
- package/livingdocs/110.PDF/090.pdf-toc-item-title/scss/pdf.scss +2 -0
- package/livingdocs/110.PDF/090.pdf-toc-item-title/scss/web.scss +1 -0
- package/livingdocs/110.PDF/090.pdf-toc-item-title/scss/word.scss +0 -0
- package/livingdocs/110.PDF/090.pdf-toc-item-title/scss/xbrl.scss +1 -0
- package/livingdocs/110.PDF/100.pdf-toc-item/pdf-toc-item.html +2 -2
- package/livingdocs/110.PDF/100.pdf-toc-item/scss/editor.scss +3 -0
- package/livingdocs/110.PDF/100.pdf-toc-item/scss/general.scss +23 -0
- package/livingdocs/110.PDF/100.pdf-toc-item/scss/pdf.scss +2 -0
- package/livingdocs/110.PDF/100.pdf-toc-item/scss/web.scss +1 -0
- package/livingdocs/110.PDF/100.pdf-toc-item/scss/word.scss +0 -0
- package/livingdocs/110.PDF/100.pdf-toc-item/scss/xbrl.scss +1 -0
- package/livingdocs/999.Properties/pdf-spacer/properties.json +7 -11
- package/livingdocs/999.Properties/pdf-spacer/scss/pdf.scss +29 -0
- package/package.json +1 -1
- package/scripts/build.js +2 -2
- package/scripts/init.js +1 -1
- package/srl/.srl/App.vue +9 -5
- package/srl/.srl/components/Srl/Article/Accordion.vue +106 -0
- package/srl/.srl/components/Srl/Article/Dialog/Button.vue +39 -16
- package/srl/.srl/components/Srl/Category/Accordion.vue +32 -4
- package/srl/.srl/plugins/initProject.ts +12 -7
- package/srl/.srl/utils/html.ts +71 -62
- package/srl/.srl/utils/index.ts +28 -1
- package/srl/.srl/utils/pageState.ts +61 -0
- package/srl/srl/pdf/PDFNotes.ts +71 -0
- package/srl/srl/pdf/PDFSetPageNumbers.ts +25 -0
- /package/srl/srl/{Awesomizr.js → pdf/Awesomizr.js} +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
@use "srl";
|
|
2
|
+
|
|
3
|
+
.srl-spacer-25 {
|
|
4
|
+
margin-top: srl.spacer-get(25) !important;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.srl-spacer-50 {
|
|
8
|
+
margin-top: srl.spacer-get(50) !important;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.srl-spacer-100 {
|
|
12
|
+
margin-top: srl.spacer-get(100) !important;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.srl-spacer-200 {
|
|
16
|
+
margin-top: srl.spacer-get(200) !important;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.srl-spacer-400 {
|
|
20
|
+
margin-top: srl.spacer-get(400) !important;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.srl-spacer-800 {
|
|
24
|
+
margin-top: srl.spacer-get(800) !important;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.srl-spacer-1600 {
|
|
28
|
+
margin-top: srl.spacer-get(1600) !important;
|
|
29
|
+
}
|
package/package.json
CHANGED
package/scripts/build.js
CHANGED
|
@@ -909,8 +909,8 @@ async function mapScss() {
|
|
|
909
909
|
await writeFileSync(
|
|
910
910
|
join(folders.srlImports, 'xbrl.scss'),
|
|
911
911
|
output.xbrl.length
|
|
912
|
-
? `@use ` + output.xbrl.join(
|
|
913
|
-
:
|
|
912
|
+
? `@use ` + output.xbrl.join(`;\n@use `)
|
|
913
|
+
: `;\n` + `;\n@use "@simple-reporting/base/scss/xbrl-core-styles.scss" as *;\n`,
|
|
914
914
|
);
|
|
915
915
|
|
|
916
916
|
return true;
|
package/scripts/init.js
CHANGED
|
@@ -58,7 +58,7 @@ async function init(folder, options) {
|
|
|
58
58
|
|
|
59
59
|
await writeFileSync(
|
|
60
60
|
`${projectPath}/.gitignore`,
|
|
61
|
-
`/.output/\n/.srl/\n/node_modules/\n/public/downloads/\n/public/html/\n/public/images/\n/public/json/\n/public/exclude/\n/dev-dist
|
|
61
|
+
`/.output/\n/.srl/\n/node_modules/\n/public/downloads/\n/public/html/\n/public/images/\n/public/json/\n/public/exclude/\n/dev-dist/\n/.DS_Store\n/.idea`,
|
|
62
62
|
);
|
|
63
63
|
console.log(`Project has created`);
|
|
64
64
|
console.log(`cd ${folder}`);
|
package/srl/.srl/App.vue
CHANGED
|
@@ -36,20 +36,24 @@
|
|
|
36
36
|
* to other components in the application.
|
|
37
37
|
*/
|
|
38
38
|
import App from '@/App.vue';
|
|
39
|
-
import { watch } from 'vue'
|
|
39
|
+
import { onMounted, watch } from 'vue'
|
|
40
40
|
import { useCssStyles } from '#composables'
|
|
41
|
+
import { setMounted } from '#utils'
|
|
41
42
|
|
|
42
|
-
const styleElement = document.createElement('style')
|
|
43
|
-
document.head.appendChild(styleElement)
|
|
43
|
+
const styleElement = document.createElement('style')
|
|
44
|
+
document.head.appendChild(styleElement)
|
|
44
45
|
|
|
45
|
-
const styleContent = useCssStyles()
|
|
46
|
+
const styleContent = useCssStyles()
|
|
46
47
|
watch(
|
|
47
48
|
styleContent.value,
|
|
48
49
|
(newStyles) => {
|
|
49
|
-
styleElement.innerHTML = newStyles.join('')
|
|
50
|
+
styleElement.innerHTML = newStyles.join('')
|
|
50
51
|
},
|
|
51
52
|
{ immediate: true },
|
|
52
53
|
);
|
|
54
|
+
onMounted(() => {
|
|
55
|
+
setMounted(true)
|
|
56
|
+
});
|
|
53
57
|
</script>
|
|
54
58
|
|
|
55
59
|
<template>
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {computed, onMounted, ref, useId} from 'vue'
|
|
3
|
+
import { useRoute } from 'vue-router'
|
|
4
|
+
import { isAccordionAnchored, setAccordionAnchored } from '#utils'
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(defineProps<{
|
|
7
|
+
toggleSelector?: string
|
|
8
|
+
contentSelector?: string
|
|
9
|
+
wrapperSelector?: string
|
|
10
|
+
openClass?: string
|
|
11
|
+
duration?: number
|
|
12
|
+
}>(), {
|
|
13
|
+
toggleSelector: '.srl-article-accordion__toggle',
|
|
14
|
+
contentSelector: '.srl-article-accordion__content',
|
|
15
|
+
wrapperSelector: '.srl-article-accordion__wrapper',
|
|
16
|
+
openClass: 'open',
|
|
17
|
+
duration: 300,
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const route = useRoute()
|
|
21
|
+
|
|
22
|
+
const id = useId()
|
|
23
|
+
const rootEl = ref<HTMLDivElement>()
|
|
24
|
+
const toggle = ref<HTMLButtonElement>()
|
|
25
|
+
const content = ref<HTMLDivElement>()
|
|
26
|
+
const wrapper = ref<HTMLDivElement>()
|
|
27
|
+
const transition = computed<string>(() => {
|
|
28
|
+
return props.duration + 'ms'
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
function open() {
|
|
32
|
+
toggle.value?.setAttribute('aria-expanded', 'true')
|
|
33
|
+
wrapper.value?.removeAttribute('hidden')
|
|
34
|
+
content.value?.classList.add(props.openClass)
|
|
35
|
+
content.value.focus()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function close() {
|
|
39
|
+
toggle.value?.setAttribute('aria-expanded', 'false')
|
|
40
|
+
content.value?.classList.remove(props.openClass)
|
|
41
|
+
setTimeout(() => {
|
|
42
|
+
wrapper.value?.setAttribute('hidden', 'true')
|
|
43
|
+
}, props.duration)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
onMounted(() => {
|
|
47
|
+
toggle.value = rootEl.value?.querySelector( props.toggleSelector ) || undefined
|
|
48
|
+
content.value = rootEl.value?.querySelector( props.contentSelector ) || undefined
|
|
49
|
+
wrapper.value = rootEl.value?.querySelector( props.wrapperSelector ) || undefined
|
|
50
|
+
|
|
51
|
+
if (toggle.value && content.value && wrapper.value) {
|
|
52
|
+
wrapper.value.setAttribute('hidden', 'true')
|
|
53
|
+
content.value.id = id
|
|
54
|
+
content.value.setAttribute('tabindex', '-1')
|
|
55
|
+
toggle.value.setAttribute('aria-controls', id)
|
|
56
|
+
|
|
57
|
+
toggle.value.addEventListener('click', () => {
|
|
58
|
+
toggle.value?.getAttribute('aria-expanded') === 'true' ? close() : open()
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
if (route.hash) {
|
|
62
|
+
if (rootEl.value.id && rootEl.value.id === route.hash) {
|
|
63
|
+
open()
|
|
64
|
+
isAccordionAnchored() || setAccordionAnchored(true)
|
|
65
|
+
} else {
|
|
66
|
+
const targetEl = rootEl.value?.querySelector<HTMLElement>(route.hash)
|
|
67
|
+
if (targetEl) {
|
|
68
|
+
open()
|
|
69
|
+
if (!isAccordionAnchored()) {
|
|
70
|
+
setAccordionAnchored(true)
|
|
71
|
+
setTimeout(() => {
|
|
72
|
+
rootEl.value?.scrollIntoView({
|
|
73
|
+
behavior: 'smooth',
|
|
74
|
+
block: 'start',
|
|
75
|
+
})
|
|
76
|
+
}, 200)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
</script>
|
|
84
|
+
|
|
85
|
+
<template>
|
|
86
|
+
<div class="srl-article-accordion" ref="rootEl" tabindex="-1">
|
|
87
|
+
<slot/>
|
|
88
|
+
</div>
|
|
89
|
+
</template>
|
|
90
|
+
|
|
91
|
+
<style lang="scss">
|
|
92
|
+
.srl-article-accordion {
|
|
93
|
+
&__content {
|
|
94
|
+
display: grid;
|
|
95
|
+
grid-template-rows: 0fr;
|
|
96
|
+
transition: grid-template-rows v-bind(transition) ease-out;
|
|
97
|
+
|
|
98
|
+
&.open {
|
|
99
|
+
grid-template-rows: 1fr;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
&__wrapper {
|
|
103
|
+
overflow: hidden;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
</style>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { ref, useId } from 'vue'
|
|
2
|
+
import { ref, useId } from 'vue'
|
|
3
3
|
import { useArticles, useConfig } from '#composables';
|
|
4
|
-
import { prepareHtmlContent } from '#utils';
|
|
4
|
+
import { prepareHtmlContent, isDialogStored, addDialogToStorage, getDialogFromStorage } from '#utils';
|
|
5
5
|
|
|
6
6
|
const props = defineProps<{
|
|
7
7
|
uuid: string;
|
|
8
|
+
anchor?: string;
|
|
8
9
|
}>();
|
|
9
10
|
|
|
10
11
|
const config = useConfig();
|
|
@@ -12,6 +13,8 @@ const articles = useArticles();
|
|
|
12
13
|
const id = ref<string>(`srl-page__dialog-${useId()}`);
|
|
13
14
|
const content = ref<string>('');
|
|
14
15
|
const dialog = ref<SrlPageDialog | null>(null);
|
|
16
|
+
let dialogStored = false
|
|
17
|
+
|
|
15
18
|
async function loadContent() {
|
|
16
19
|
const article = articles.value.find((article) => article.uuid === props.uuid);
|
|
17
20
|
if (article) {
|
|
@@ -20,35 +23,55 @@ async function loadContent() {
|
|
|
20
23
|
const req = await fetch(file);
|
|
21
24
|
const text = await req.text();
|
|
22
25
|
content.value = prepareHtmlContent(text);
|
|
26
|
+
// Do something with anchor if provided
|
|
27
|
+
/*
|
|
28
|
+
if (props.anchor) {
|
|
29
|
+
nextTick(() => {
|
|
30
|
+
// Do action
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
*/
|
|
23
34
|
} catch (error) {
|
|
24
35
|
console.error(`Failed to load article content from ${file}:`, error);
|
|
25
36
|
}
|
|
26
37
|
}
|
|
27
38
|
}
|
|
28
39
|
|
|
29
|
-
|
|
40
|
+
if (isDialogStored(props.uuid)) {
|
|
41
|
+
dialogStored = true;
|
|
42
|
+
} else {
|
|
43
|
+
addDialogToStorage(props.uuid, dialog);
|
|
44
|
+
loadContent();
|
|
45
|
+
}
|
|
46
|
+
|
|
30
47
|
async function open() {
|
|
31
|
-
dialog.value
|
|
48
|
+
if (dialog.value) {
|
|
49
|
+
dialog.value.open();
|
|
50
|
+
} else {
|
|
51
|
+
const storage = getDialogFromStorage(props.uuid);
|
|
52
|
+
storage ?
|
|
53
|
+
storage.open():
|
|
54
|
+
console.warn(`Dialog with uuid ${props.uuid} not found in storage.`);
|
|
55
|
+
}
|
|
32
56
|
}
|
|
33
57
|
</script>
|
|
34
58
|
|
|
35
59
|
<template>
|
|
36
60
|
<button
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
61
|
+
class="srl-dialog-button"
|
|
62
|
+
type="button"
|
|
63
|
+
:aria-controls="id"
|
|
64
|
+
aria-haspopup="dialog"
|
|
65
|
+
:aria-expanded="dialog?.dialogState ?? false"
|
|
66
|
+
@click="open"
|
|
43
67
|
>
|
|
44
68
|
<slot />
|
|
45
|
-
<Teleport to="body">
|
|
69
|
+
<Teleport v-if="content" to="body">
|
|
46
70
|
<SrlPageDialog
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
@close="expanded = false"
|
|
71
|
+
:id="id"
|
|
72
|
+
ref="dialog"
|
|
73
|
+
:content="content"
|
|
74
|
+
@close="expanded = false"
|
|
52
75
|
/>
|
|
53
76
|
</Teleport>
|
|
54
77
|
</button>
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed, ref, useId } from 'vue'
|
|
2
|
+
import { computed, nextTick, onMounted, ref, useId } from 'vue'
|
|
3
|
+
import { useRoute } from 'vue-router'
|
|
4
|
+
import { isAccordionAnchored, setAccordionAnchored } from '#utils'
|
|
3
5
|
|
|
4
6
|
const rootEl = ref<HTMLElement | null>(null)
|
|
5
7
|
const id = ref(useId())
|
|
6
8
|
const state = ref(false)
|
|
9
|
+
const route = useRoute()
|
|
7
10
|
function toggle() {
|
|
8
11
|
state.value ?
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
close() :
|
|
13
|
+
open()
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
function open() {
|
|
@@ -32,10 +35,35 @@ const accordion = computed(() => {
|
|
|
32
35
|
}
|
|
33
36
|
})
|
|
34
37
|
|
|
38
|
+
onMounted(() => {
|
|
39
|
+
if (route.hash) {
|
|
40
|
+
if (rootEl.value.id && rootEl.value.id === route.hash) {
|
|
41
|
+
open()
|
|
42
|
+
isAccordionAnchored() || setAccordionAnchored(true)
|
|
43
|
+
} else {
|
|
44
|
+
const targetEl = rootEl.value?.querySelector<HTMLElement>(route.hash)
|
|
45
|
+
if (targetEl) {
|
|
46
|
+
open()
|
|
47
|
+
if (!isAccordionAnchored()) {
|
|
48
|
+
setAccordionAnchored(true)
|
|
49
|
+
nextTick(() => {
|
|
50
|
+
setTimeout(() => {
|
|
51
|
+
rootEl.value.scrollIntoView({
|
|
52
|
+
behavior: 'smooth',
|
|
53
|
+
block: 'start',
|
|
54
|
+
})
|
|
55
|
+
}, 200)
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
|
|
35
63
|
</script>
|
|
36
64
|
|
|
37
65
|
<template>
|
|
38
|
-
<div ref="rootEl">
|
|
66
|
+
<div ref="rootEl" tabindex="-1">
|
|
39
67
|
<slot :accordion="accordion"/>
|
|
40
68
|
</div>
|
|
41
69
|
</template>
|
|
@@ -2,6 +2,7 @@ import { setConfig } from '#composables/config';
|
|
|
2
2
|
import { createApp } from 'vue';
|
|
3
3
|
import { initI18n } from '@/i18n';
|
|
4
4
|
import srlVuePlugin from '#plugins/vueSrlPlugin';
|
|
5
|
+
import { clearPageState } from '#utils'
|
|
5
6
|
|
|
6
7
|
import '#imports/app.scss';
|
|
7
8
|
|
|
@@ -9,11 +10,15 @@ import SrlPageApp from '../App.vue';
|
|
|
9
10
|
import router from '@/router';
|
|
10
11
|
|
|
11
12
|
export default async function initProject() {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
router.beforeEach((to, from, next) => {
|
|
14
|
+
clearPageState();
|
|
15
|
+
next();
|
|
16
|
+
});
|
|
17
|
+
await setConfig();
|
|
18
|
+
const i18n = initI18n();
|
|
19
|
+
const app = (window.app = createApp(SrlPageApp));
|
|
20
|
+
app.use(i18n);
|
|
21
|
+
app.use(router);
|
|
22
|
+
app.use(srlVuePlugin);
|
|
23
|
+
return app;
|
|
19
24
|
}
|
package/srl/.srl/utils/html.ts
CHANGED
|
@@ -3,83 +3,92 @@ import { useArticles, useLocale, addCssStyles } from '#composables';
|
|
|
3
3
|
|
|
4
4
|
type AttrObj = { [key: string]: string | null };
|
|
5
5
|
function attributesToString(attributes: Record<string, string | null>): string {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
return Object.entries(attributes)
|
|
7
|
+
.map(([key, value]) => (value !== null ? `${key}="${value}"` : key))
|
|
8
|
+
.join(' ');
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export function prepareHtmlContent(text: string): string {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const articles = useArticles();
|
|
13
|
+
const locale = useLocale();
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const regex = /<a\s+([^>]+)>(.*?)<\/a>/gis;
|
|
16
|
+
text = text.replace(regex, (match, attrString, innerText) => {
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
const attrObj: AttrObj = {};
|
|
19
|
+
attrString.replace(/([a-zA-Z0-9\-_]+)(?:="([^"]*)")?/g, (m, key: string, value: string | null) => {
|
|
20
|
+
attrObj[key] = value || null;
|
|
21
|
+
return m;
|
|
22
|
+
});
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
if (
|
|
25
|
+
attrObj['data-note-target'] &&
|
|
26
|
+
attrObj['data-note-target'] === 'popup'
|
|
27
|
+
) {
|
|
28
|
+
attrObj.uuid = attrObj.href;
|
|
29
|
+
delete attrObj.href;
|
|
30
|
+
if (attrObj['data-article-name']) {
|
|
31
|
+
attrObj.uuid = attrObj['data-article-name'];
|
|
32
|
+
delete attrObj['data-article-name'];
|
|
33
|
+
}
|
|
34
|
+
const arrUuid = attrObj.uuid.split('#');
|
|
35
|
+
attrObj.uuid = arrUuid[0];
|
|
36
|
+
if (arrUuid[1]) {
|
|
37
|
+
attrObj.anchor = arrUuid[1];
|
|
38
|
+
}
|
|
39
|
+
const attrs = attributesToString(attrObj);
|
|
40
|
+
return `<srl-article-dialog-button ${attrs}>${innerText}</srl-article-dialog-button>`;
|
|
41
|
+
}
|
|
33
42
|
|
|
34
|
-
|
|
35
|
-
|
|
43
|
+
if (attrObj.href) {
|
|
44
|
+
const arrLink = attrObj.href.split('#');
|
|
36
45
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
if (isRouterPath(arrLink[0])) {
|
|
47
|
+
delete attrObj.href;
|
|
48
|
+
if (arrLink[0].startsWith('./')) {
|
|
49
|
+
arrLink[0] = arrLink[0].substring(1);
|
|
50
|
+
}
|
|
51
|
+
if (arrLink[0] === `/${locale.value}/home`) {
|
|
52
|
+
arrLink[0] = `/${locale.value}`;
|
|
53
|
+
}
|
|
54
|
+
attrObj.to = arrLink[0];
|
|
55
|
+
if (arrLink[1]) {
|
|
56
|
+
attrObj.to += `#${arrLink[1]}`;
|
|
57
|
+
}
|
|
58
|
+
const attrs = attributesToString(attrObj);
|
|
59
|
+
return `<router-link ${attrs}>${innerText}</router-link>`;
|
|
60
|
+
}
|
|
52
61
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
const a = articles.value.find((i) => i.uuid === arrLink[0]);
|
|
63
|
+
if (a) {
|
|
64
|
+
delete attrObj.href;
|
|
65
|
+
attrObj.to = a.index
|
|
66
|
+
? `/${locale.value}`
|
|
67
|
+
: `/${locale.value}/${a.slug}`;
|
|
68
|
+
if (arrLink[1]) {
|
|
69
|
+
attrObj.to += `#${arrLink[1]}`;
|
|
70
|
+
}
|
|
71
|
+
const attrs = attributesToString(attrObj);
|
|
72
|
+
return `<router-link ${attrs}>${innerText}</router-link>`;
|
|
73
|
+
}
|
|
61
74
|
}
|
|
62
|
-
const attrs = attributesToString(attrObj);
|
|
63
|
-
return `<router-link ${attrs}>${innerText}</router-link>`;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
75
|
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
return match;
|
|
77
|
+
});
|
|
69
78
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
text = text.replace(
|
|
80
|
+
/<template-([a-z]+)>([\s\S]*?)<\/template-\1>/g,
|
|
81
|
+
(_match, name, content) => `<template #${name}>${content}</template>`
|
|
82
|
+
);
|
|
74
83
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
84
|
+
text = text.replace(/<style[^>]*>([\s\S]*?)<\/style>/gi, (match, p1) => {
|
|
85
|
+
addCssStyles(p1);
|
|
86
|
+
return '';
|
|
87
|
+
});
|
|
79
88
|
|
|
80
|
-
|
|
89
|
+
return text;
|
|
81
90
|
}
|
|
82
91
|
|
|
83
92
|
export default {
|
|
84
|
-
|
|
93
|
+
prepareHtmlContent,
|
|
85
94
|
};
|
package/srl/.srl/utils/index.ts
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
import { isRouterPath, isExternalPath } from './uri';
|
|
2
2
|
import { camelCase } from './camelCase';
|
|
3
3
|
import { prepareHtmlContent } from './html';
|
|
4
|
+
import {
|
|
5
|
+
usePageState,
|
|
6
|
+
clearPageState,
|
|
7
|
+
isDialogStored,
|
|
8
|
+
addDialogToStorage,
|
|
9
|
+
getDialogFromStorage,
|
|
10
|
+
getDialogStorage,
|
|
11
|
+
isAccordionAnchored,
|
|
12
|
+
setAccordionAnchored,
|
|
13
|
+
isMounted,
|
|
14
|
+
setMounted
|
|
15
|
+
} from './pageState.ts';
|
|
4
16
|
|
|
5
|
-
export {
|
|
17
|
+
export {
|
|
18
|
+
isRouterPath,
|
|
19
|
+
isExternalPath,
|
|
20
|
+
camelCase,
|
|
21
|
+
prepareHtmlContent,
|
|
22
|
+
usePageState,
|
|
23
|
+
clearPageState,
|
|
24
|
+
isAccordionAnchored,
|
|
25
|
+
setAccordionAnchored,
|
|
26
|
+
isDialogStored,
|
|
27
|
+
addDialogToStorage,
|
|
28
|
+
getDialogFromStorage,
|
|
29
|
+
getDialogStorage,
|
|
30
|
+
setMounted,
|
|
31
|
+
isMounted,
|
|
32
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type Ref } from 'vue'
|
|
2
|
+
|
|
3
|
+
type DialogStorage = {
|
|
4
|
+
[key: string]: Ref<SrlPageDialog>;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type PageState = {
|
|
8
|
+
isMounted: boolean;
|
|
9
|
+
dialogStorage: DialogStorage;
|
|
10
|
+
accordionAnchored: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const pageState: PageState = {
|
|
14
|
+
isMounted: false,
|
|
15
|
+
dialogStorage: {},
|
|
16
|
+
accordionAnchored: false,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function usePageState() {
|
|
20
|
+
return pageState;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function setMounted(value: boolean): void {
|
|
24
|
+
pageState.isMounted = value;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function isMounted(): boolean {
|
|
28
|
+
return pageState.isMounted;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function clearPageState() {
|
|
32
|
+
pageState.isMounted = false;
|
|
33
|
+
pageState.dialogStorage = {};
|
|
34
|
+
pageState.accordionAnchored = false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function isDialogStored(uuid: string): boolean {
|
|
38
|
+
return uuid in pageState.dialogStorage
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function addDialogToStorage(uuid: string, refSrlPageDialog: Ref<SrlPageDialog>): void {
|
|
42
|
+
pageState.dialogStorage[uuid] = refSrlPageDialog
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function getDialogFromStorage(uuid: string): SrlPageDialog | null {
|
|
46
|
+
return isDialogStored(uuid)?
|
|
47
|
+
pageState.dialogStorage[uuid].value : null
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function getDialogStorage() : DialogStorage {
|
|
51
|
+
return pageState.dialogStorage
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function setAccordionAnchored(value: boolean): void {
|
|
55
|
+
pageState.accordionAnchored = value;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function isAccordionAnchored(): boolean {
|
|
59
|
+
return pageState.accordionAnchored;
|
|
60
|
+
}
|
|
61
|
+
|