Skip to content
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
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<Faq>
#### Wo finde ich weitere Informationen und Anleitungen zur __<span title="Multi-Faktor-Authentifikation">MFA</span>__?

<Solution>
Eine detaillierte Anleitung von EDUBERN finden Sie hier: [EDUBERN: Anleitung MFA](https://erzbe.sharepoint.com/sites/EDUBERN-Infohub-Hilfsmittel/Lists/Hilfsmittel/Attachments/4/Anleitung%20-%20Einrichten%20MFA%20EDUBERN%20.pdf).
Offizielle Anleitungen von EDUBERN finden Sie hier:
- [EDUBERN Kurzanleitung Account & MFA](@office-onboarding-short)
- [EDUBERN detaillierte Anleitung Account & MFA](@office-onboarding-long)
- [EDUBERN Anleitung MFA ohne Handy](@mfa-ohne-handy)
</Solution>
</Faq>
3 changes: 3 additions & 0 deletions docs/link-mappings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mfa-ohne-handy: "https://erzbe.sharepoint.com/sites/EDUBERN-Infohub-Hilfsmittel/Lists/Hilfsmittel/Attachments/21/Anleitung_MFA_ohne_Handy.pdf"
office-onboarding-short: "https://erzbe.sharepoint.com/sites/EDUBERN-Infohub-Hilfsmittel/Lists/Hilfsmittel/Attachments/157/Anleitung%20%e2%80%93%20Onboarding%20EDUBERN_BYOD_RESET_D_SHORT.pdf"
office-onboarding-long: "https://erzbe.sharepoint.com/sites/EDUBERN-Infohub-Hilfsmittel/Lists/Hilfsmittel/Attachments/157/Anleitung%20%e2%80%93%20Onboarding%20EDUBERN%20BYOD%20FED_RESET_D.pdf"
39 changes: 39 additions & 0 deletions packages/ict/link-mapping/README.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
page_id: 979630e9-9272-410b-a7c1-fe40601be7a4
---

# Link Mapping

Mit `@ict/link-mapping` lassen sich links in einer `.yaml`-Datei festlegen und dann als Markdown-Link verwenden.

```yaml
foo: https://foo.com
bar: https://bar.com
```
```md
Auf [foo](@foo) sieht man einen Link zu [bar](@bar).
```

Der MD-Link muss mit einem @ beginnen, damit es der Schlüssel im YAML gesucht wird.

## Vorteile
Links sind an einem Ort und können leicht überprüft/aktualisiert werden, ggf. auch automatisch.

## Installation

```ts title="siteConfig.ts"
import linkMappingPlugin from '@ict/link-mapping';

const getSiteConfig: SiteConfigProvider = () => {
return {
/*...*/
remarkPlugins: [
/*...*/
// highlight-next-line
[linkMappingPlugin, { mappingFilePath: './docs/link-mappings.yaml' }]
/*...*/
],
}
}
```
66 changes: 66 additions & 0 deletions packages/ict/link-mapping/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { visit } from 'unist-util-visit';
import type { Plugin, Transformer } from 'unified';
import { Root, Text } from 'mdast';
import * as yaml from 'js-yaml';
import * as fs from 'fs/promises';
import path from 'path';

interface OptionsInput {
mapping: Record<string, string>;
mappingFilePath?: string;
}

const links = new Map<string, string>();
let lastModifiedTime = 0;

const loadMapping = async (mappingFilePath?: string) => {
if (!mappingFilePath) {
return;
}
// get time of last modification of the mapping file
const stats = await fs.stat(mappingFilePath).catch((err) => {
return { mtimeMs: 0 };
});
const lastModified = stats.mtimeMs;

if (lastModified <= lastModifiedTime) {
return;
}
if (lastModified > lastModifiedTime) {
lastModifiedTime = lastModified;
const fileContent = await fs.readFile(mappingFilePath, 'utf8').catch((err) => {
console.error(`Error reading mapping file at ${mappingFilePath}:`, err);
return '';
});
const mapping = yaml.load(fileContent) as Record<string, string>;
// don't clear the links map, instead just update it with new values
// links.clear();
for (const [key, value] of Object.entries(mapping)) {
links.set(key, value);
}
}
};

const plugin: Plugin<OptionsInput[], Root> = function plugin(
optionsInput = { mapping: {} }
): Transformer<Root> {
for (const [key, value] of Object.entries(optionsInput.mapping ?? {})) {
links.set(key, value);
}

return async (tree) => {
await loadMapping(optionsInput.mappingFilePath);
visit(tree, 'link', (node) => {
if (!node.url.startsWith('@')) {
return;
}
const translationKey = node.url.slice(1);
if (!links.has(translationKey)) {
return;
}
node.url = links.get(translationKey) ?? node.url;
});
};
};

export default plugin;
19 changes: 19 additions & 0 deletions packages/ict/link-mapping/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "@ict/link-mapping",
"version": "1.0.0",
"main": "index.ts",
"types": "index.ts",
"dependencies": {

},
"devDependencies": {
"vitest": "*",
"@docusaurus/module-type-aliases": "*",
"@docusaurus/core": "*"
},
"peerDependencies": {
"@tdev/core": "1.0.0",
"js-yaml": "*",
"@types/js-yaml": "*"
}
}
38 changes: 38 additions & 0 deletions packages/ict/link-mapping/tests/plugin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { remark } from 'remark';
import remarkMdx from 'remark-mdx';
import remarkDirective from 'remark-directive';
import { describe, expect, it } from 'vitest';

const process = async (content: string, mapping: Record<string, string> = {}) => {
const { default: plugin } = await import('..');
const result = await remark()
.use(remarkMdx)
.use(remarkDirective)
.use(plugin, { mapping })
.process(content);

return result.value;
};

describe('#link annotation', () => {
it("does nothing if there's no link", async () => {
const input = `# Heading

Some content
`;
const result = await process(input);
expect(result).toBe(input);
});
it('can map links', async () => {
const input = `# Details element example
Hello [example](@translation-key) world!
`;
const result = await process(input, { ['translation-key']: 'https://example.org' });
expect(result).toMatchInlineSnapshot(`
"# Details element example

Hello [example](https://example.org) world!
"
`);
});
});
3 changes: 3 additions & 0 deletions packages/ict/link-mapping/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "../../../tsconfig.package.json"
}
8 changes: 5 additions & 3 deletions siteConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const ADMONITION_CONFIG = {
};
import dynamicRouter from './src/plugins/plugin-dynamic-routes';
import { type DirectusConfig } from '@ict/directus';
import linkMappingPlugin from '@ict/link-mapping';

declare module './src/siteConfig/siteConfig' {
export interface TdevConfig {
Expand Down Expand Up @@ -154,9 +155,10 @@ const getSiteConfig: SiteConfigProvider = () => {
}
]
] as unknown as PluginOptions[],
remarkPlugins: recommendedRemarkPlugins.filter(
(p) => p !== commentPluginConfig
) as unknown as PluginOptions[],
remarkPlugins: [
[linkMappingPlugin, { mappingFilePath: './docs/link-mappings.yaml' }],
...recommendedRemarkPlugins.filter((p) => p !== commentPluginConfig)
] as unknown as PluginOptions[],
apiDocumentProviders: [
require.resolve('@tdev/page-read-check/register'),
require.resolve('@ict/directus/register')
Expand Down
Loading