Skip to content
Closed
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
27 changes: 27 additions & 0 deletions docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,33 @@ Disqus comments. https://disqus.com/
</script>
```

## OneTag AI

[OneTag AI](https://onetagai.com) adds an "ask this page" button. Visitors type a question and get an answer drawn from the page they are reading.

The key is a public site key with a hard usage cap, so it can be committed with your docs. Get one for free at https://onetagai.com.

```html
<script>
window.$docsify = {
onetag: 'your-onetag-key',
};
</script>
<script src="//cdn.jsdelivr.net/npm/docsify@5/dist/plugins/onetag.min.js"></script>
```

Pass an object to set the [widget options](https://onetagai.com/docs#widget):

```js
window.$docsify = {
onetag: {
key: 'your-onetag-key',
title: 'Ask the docs',
theme: 'dark', // 'light', 'dark' or 'auto' (default)
},
};
```

## Pagination

Pagination for docsify. By [@imyelo](https://github.com/imyelo)
Expand Down
36 changes: 36 additions & 0 deletions src/plugins/onetag.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// OneTag AI "ask this page" button — https://onetagai.com
// Visitors type a question and get an answer drawn from the page they are reading.

const window = /** @type {any} */ (globalThis);

function install(hook, vm) {
const config = vm.config.onetag;
const options = typeof config === 'string' ? { key: config } : { ...config };

if (!options.key) {
// eslint-disable-next-line no-console
console.error('[Docsify] onetag key is required.');
return;
}

hook.mounted(_ => {
const script = document.createElement('script');

script.async = true;
script.src = 'https://onetagai.com/widget.js';

// Answers are drawn from the rendered page, not from the sidebar or navbar.
Object.assign(script.dataset, {
ref: 'docsify',
source: '.markdown-section',
...options,
});

document.body.appendChild(script);
});
}

window.$docsify = window.$docsify || {};
window.$docsify.plugins = [install, ...(window.$docsify.plugins || [])];

export {};
73 changes: 73 additions & 0 deletions test/e2e/onetag.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import docsifyInit from '../helpers/docsify-init.js';
import { test, expect } from './fixtures/docsify-init-fixture.js';

test.describe('OneTag Plugin Tests', () => {
const widgetURL = 'https://onetagai.com/widget.js';
const widgetSelector = `script[src="${widgetURL}"]`;

// The widget script is replaced with a stub so that tests do not depend on the network
async function stubWidget(page) {
await page.route(widgetURL, route =>
route.fulfill({
contentType: 'text/javascript',
body: 'window.onetagDataset = { ...document.currentScript.dataset };',
}),
);
}

test('key as a string', async ({ page }) => {
await stubWidget(page);
await docsifyInit({
config: {
onetag: 'ot_test',
},
scriptURLs: ['/dist/plugins/onetag.js'],
});

await expect
.poll(() => page.evaluate(() => window.onetagDataset))
.toEqual({
key: 'ot_test',
ref: 'docsify',
source: '.markdown-section',
});
await expect(page.locator(widgetSelector)).toHaveCount(1);
});

test('options as an object', async ({ page }) => {
await stubWidget(page);
await docsifyInit({
config: {
onetag: {
key: 'ot_test',
position: 'left',
title: 'Ask the docs',
},
},
scriptURLs: ['/dist/plugins/onetag.js'],
});

await expect
.poll(() => page.evaluate(() => window.onetagDataset))
.toEqual({
key: 'ot_test',
position: 'left',
ref: 'docsify',
source: '.markdown-section',
title: 'Ask the docs',
});
});

test('nothing is loaded without a key', async ({ page }) => {
const consoleMsgs = [];

page.on('console', msg => consoleMsgs.push(msg.text()));
await stubWidget(page);
await docsifyInit({
scriptURLs: ['/dist/plugins/onetag.js'],
});

await expect(page.locator(widgetSelector)).toHaveCount(0);
expect(consoleMsgs).toContain('[Docsify] onetag key is required.');
});
});