mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-05 03:57:03 -04:00
129 lines
3.6 KiB
Vue
129 lines
3.6 KiB
Vue
<script lang="ts">
|
|
import { defineComponent, h } from 'vue';
|
|
import type { VNode } from 'vue';
|
|
|
|
import useConfig from '../composables/useConfig.ts';
|
|
import useSpelling from '../composables/useSpelling.ts';
|
|
import { escapeHtml } from '../src/helpers.ts';
|
|
|
|
import Icon from './Icon.vue';
|
|
|
|
import { NuxtLink } from '#components';
|
|
|
|
export default defineComponent({
|
|
props: {
|
|
text: { default: '', type: String },
|
|
noicons: { type: Boolean },
|
|
escape: { type: Boolean },
|
|
},
|
|
setup() {
|
|
const { handleSpelling } = useSpelling();
|
|
return {
|
|
config: useConfig(),
|
|
handleSpelling,
|
|
};
|
|
},
|
|
render() {
|
|
let text = this.text;
|
|
if (this.escape) {
|
|
text = escapeHtml(text);
|
|
}
|
|
if (!text) {
|
|
return h('span', this.$attrs);
|
|
}
|
|
|
|
let isLink = false;
|
|
let isIcon = false;
|
|
let isEscape = false;
|
|
let buffer = '';
|
|
let linkBuffer = '';
|
|
const children: VNode[] = [];
|
|
const buildLink = (): VNode => {
|
|
if (isIcon) {
|
|
return h(Icon, { v: buffer });
|
|
}
|
|
|
|
const attrs = { ...this.$attrs, innerHTML: this.handleSpelling(buffer) };
|
|
|
|
if (!isLink) {
|
|
return h('span', attrs);
|
|
}
|
|
|
|
linkBuffer = linkBuffer.replace(/≡/g, '='); // meh workaround, i know…
|
|
|
|
if (linkBuffer === '') {
|
|
linkBuffer = `#${buffer}`;
|
|
}
|
|
|
|
if (linkBuffer.startsWith('https://') ||
|
|
linkBuffer.startsWith('http://') ||
|
|
linkBuffer.startsWith('mailto:') ||
|
|
linkBuffer.endsWith('.pdf')
|
|
) {
|
|
return h(
|
|
'a',
|
|
{ ...attrs, href: linkBuffer, target: '_blank', rel: 'noopener' },
|
|
);
|
|
}
|
|
|
|
if (linkBuffer.indexOf('#') === 0) {
|
|
return h('a', { ...attrs, href: linkBuffer });
|
|
}
|
|
|
|
const to = encodeURI(linkBuffer) || `/${this.config.nouns.route}#${this.handleSpelling(buffer)}`;
|
|
return h(NuxtLink, { ...attrs, to });
|
|
};
|
|
const addChild = (): void => {
|
|
if (!buffer) {
|
|
return;
|
|
}
|
|
children.push(buildLink());
|
|
buffer = '';
|
|
linkBuffer = '';
|
|
};
|
|
for (const c of text) {
|
|
if (c === '{') {
|
|
addChild();
|
|
isLink = true;
|
|
continue;
|
|
} else if (c === '}') {
|
|
addChild();
|
|
isLink = false;
|
|
continue;
|
|
} else if (isLink && c === '=') {
|
|
if (linkBuffer) {
|
|
linkBuffer += '=';
|
|
}
|
|
linkBuffer += buffer;
|
|
buffer = '';
|
|
continue;
|
|
} else if (c === '[' && !this.noicons) {
|
|
addChild();
|
|
if (isEscape) {
|
|
isEscape = false;
|
|
} else {
|
|
isIcon = true;
|
|
continue;
|
|
}
|
|
} else if (c === ']' && !this.noicons) {
|
|
addChild();
|
|
if (isIcon) {
|
|
isIcon = false;
|
|
continue;
|
|
}
|
|
} else if (c === '\\') {
|
|
isEscape = true;
|
|
continue;
|
|
} else if (isEscape) {
|
|
buffer += '\\';
|
|
isEscape = false;
|
|
}
|
|
buffer += c;
|
|
}
|
|
addChild();
|
|
|
|
return children;
|
|
},
|
|
});
|
|
</script>
|