tona-plugins 1.0.1

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.
Files changed (71) hide show
  1. package/README.md +48 -0
  2. package/index.d.ts +32 -0
  3. package/package.json +51 -0
  4. package/src/constants/cdn.js +12 -0
  5. package/src/index.js +30 -0
  6. package/src/plugins/background/index.js +50 -0
  7. package/src/plugins/background/index.scss +0 -0
  8. package/src/plugins/barrage/index.js +104 -0
  9. package/src/plugins/barrage/index.scss +16 -0
  10. package/src/plugins/catalog/index.js +212 -0
  11. package/src/plugins/catalog/index.scss +0 -0
  12. package/src/plugins/charts/index.js +60 -0
  13. package/src/plugins/charts/index.scss +16 -0
  14. package/src/plugins/clickEffects/index.js +137 -0
  15. package/src/plugins/clickEffects/index.scss +0 -0
  16. package/src/plugins/codeCopy/index.js +94 -0
  17. package/src/plugins/codeCopy/index.scss +65 -0
  18. package/src/plugins/codeHighlight/index.js +35 -0
  19. package/src/plugins/codeHighlight/index.scss +216 -0
  20. package/src/plugins/codeHighlight/themes.js +60 -0
  21. package/src/plugins/codeLang/index.js +51 -0
  22. package/src/plugins/codeLang/index.scss +28 -0
  23. package/src/plugins/codeLinenumbers/index.js +33 -0
  24. package/src/plugins/codeLinenumbers/index.scss +61 -0
  25. package/src/plugins/codeTrafficLight/index.js +18 -0
  26. package/src/plugins/codeTrafficLight/index.scss +0 -0
  27. package/src/plugins/colorMode/index.js +81 -0
  28. package/src/plugins/colorMode/index.scss +0 -0
  29. package/src/plugins/commentsAvatars/index.js +85 -0
  30. package/src/plugins/commentsAvatars/index.scss +3 -0
  31. package/src/plugins/darkMode/index.js +115 -0
  32. package/src/plugins/darkMode/index.scss +67 -0
  33. package/src/plugins/donation/index.js +45 -0
  34. package/src/plugins/donation/index.scss +63 -0
  35. package/src/plugins/emoji/index.js +167 -0
  36. package/src/plugins/emoji/index.scss +155 -0
  37. package/src/plugins/footer/index.js +35 -0
  38. package/src/plugins/footer/index.scss +54 -0
  39. package/src/plugins/imagePreview/index.js +98 -0
  40. package/src/plugins/imagePreview/index.scss +51 -0
  41. package/src/plugins/license/index.js +62 -0
  42. package/src/plugins/license/index.scss +51 -0
  43. package/src/plugins/live2d/index.js +67 -0
  44. package/src/plugins/live2d/index.scss +0 -0
  45. package/src/plugins/live2d/live2d-models.js +21 -0
  46. package/src/plugins/lock/index.js +77 -0
  47. package/src/plugins/lock/index.scss +56 -0
  48. package/src/plugins/musicPlayer/index.js +81 -0
  49. package/src/plugins/musicPlayer/index.scss +68 -0
  50. package/src/plugins/notation/index.js +73 -0
  51. package/src/plugins/notation/index.scss +12 -0
  52. package/src/plugins/notice/index.js +17 -0
  53. package/src/plugins/notice/index.scss +46 -0
  54. package/src/plugins/postBottomImage/index.js +27 -0
  55. package/src/plugins/postBottomImage/index.scss +26 -0
  56. package/src/plugins/postMessage/index.js +89 -0
  57. package/src/plugins/postMessage/index.scss +81 -0
  58. package/src/plugins/postTopImage/index.js +28 -0
  59. package/src/plugins/postTopImage/index.scss +29 -0
  60. package/src/plugins/qrcode/index.js +42 -0
  61. package/src/plugins/qrcode/index.scss +10 -0
  62. package/src/plugins/signature/index.js +47 -0
  63. package/src/plugins/signature/index.scss +18 -0
  64. package/src/plugins/toast/index.js +49 -0
  65. package/src/plugins/tools/index.js +251 -0
  66. package/src/plugins/tools/index.scss +114 -0
  67. package/src/plugins/webTag/index.js +40 -0
  68. package/src/plugins/webTag/index.scss +0 -0
  69. package/src/utils/cnblog.js +282 -0
  70. package/src/utils/helpers.js +418 -0
  71. package/src/utils/shared.js +2 -0
package/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # plugins
2
+
3
+ Plugins for Tona theme.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ npm i tona
9
+ ```
10
+
11
+ ```bash
12
+ npm i tona-plugins
13
+ ```
14
+
15
+ ```js
16
+ import { createTheme } from 'tona'
17
+ import { background } from 'tona-plugins'
18
+
19
+ createTheme().use(background)
20
+ ```
21
+
22
+ Configure the default behavior of the plugin in your Theme
23
+
24
+ ```js
25
+ import { createTheme } from 'tona'
26
+ import { background } from 'tona-plugins'
27
+
28
+ createTheme().use(background, {
29
+ // The default configuration of the Theme
30
+ enable: true,
31
+ })
32
+ ```
33
+
34
+ Configure background plugin
35
+
36
+ ```js
37
+ import { createTheme } from 'tona'
38
+ import { background } from 'tona-plugins'
39
+
40
+ createTheme().use(
41
+ background,
42
+ {},
43
+ {
44
+ // The configuration of the plugin
45
+ opacitySelector: '#sideBar,#mainContent,#footer',
46
+ }
47
+ )
48
+ ```
package/index.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ declare module 'tona-plugins' {
2
+ export function musicPlayer(theme: any, devOptions?: any): void
3
+ export function background(theme: any, devOptions?: any): void
4
+ export function barrage(theme: any, devOptions?: any): void
5
+ export function catalog(theme: any, devOptions?: any): void
6
+ export function charts(theme: any, devOptions?: any): void
7
+ export function clickEffects(theme: any, devOptions?: any): void
8
+ export function codeCopy(theme: any, devOptions?: any): void
9
+ export function codeHighlight(theme: any, devOptions?: any): void
10
+ export function codeLang(theme: any, devOptions?: any): void
11
+ export function codeLinenumbers(theme: any, devOptions?: any): void
12
+ export function codeTrafficLight(theme: any, devOptions?: any): void
13
+ export function colorMode(theme: any, devOptions?: any): void
14
+ export function commentsAvatars(theme: any, devOptions?: any): void
15
+ export function darkMode(theme: any, devOptions?: any): void
16
+ export function donation(theme: any, devOptions?: any): void
17
+ export function emoji(theme: any, devOptions?: any): void
18
+ export function footer(theme: any, devOptions?: any): void
19
+ export function imagePreview(theme: any, devOptions?: any): void
20
+ export function license(theme: any, devOptions?: any): void
21
+ export function live2d(theme: any, devOptions?: any): void
22
+ export function lock(theme: any, devOptions?: any): void
23
+ export function notation(theme: any, devOptions?: any): void
24
+ export function notice(theme: any, devOptions?: any): void
25
+ export function postBottomImage(theme: any, devOptions?: any): void
26
+ export function postMessage(theme: any, devOptions?: any): void
27
+ export function postTopImage(theme: any, devOptions?: any): void
28
+ export function qrcode(theme: any, devOptions?: any): void
29
+ export function signature(theme: any, devOptions?: any): void
30
+ export function tools(theme: any, devOptions?: any): void
31
+ export function webTag(theme: any, devOptions?: any): void
32
+ }
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "tona-plugins",
3
+ "version": "1.0.1",
4
+ "description": "",
5
+ "author": {
6
+ "name": "guangzan",
7
+ "url": "https://www.cnblogs.com/guangzan",
8
+ "email": "guangzan1999@outlook.com"
9
+ },
10
+ "license": "MIT",
11
+ "homepage": "https://github.com/acnblogs/tona#readme",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/acnblogs/tona.git"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/acnblogs/tona/issues"
18
+ },
19
+ "keywords": [
20
+ "博客园"
21
+ ],
22
+ "exports": {
23
+ ".": {
24
+ "types": "./index.d.ts",
25
+ "import": "./src/index.js"
26
+ }
27
+ },
28
+ "main": "./src/index.js",
29
+ "module": "./src/index.js",
30
+ "types": "./index.d.ts",
31
+ "files": [
32
+ "index.d.ts",
33
+ "src"
34
+ ],
35
+ "dependencies": {
36
+ "notyf": "^3.10.0",
37
+ "tona-options": "1.0.1",
38
+ "tona": "1.0.1"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^25.0.3",
42
+ "sass": "^1.97.2",
43
+ "vite": "^7.3.1",
44
+ "vite-plugin-html": "^3.2.2",
45
+ "vite-plugin-singlefile": "^2.3.0",
46
+ "tona-vite": "1.0.1"
47
+ },
48
+ "scripts": {
49
+ "dev": "vite"
50
+ }
51
+ }
@@ -0,0 +1,12 @@
1
+ export const chartJs =
2
+ 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js'
3
+ export const mediaZoomJs =
4
+ 'https://cdnjs.cloudflare.com/ajax/libs/medium-zoom/1.0.6/medium-zoom.min.js'
5
+ export const APlayerJs =
6
+ 'https://cdnjs.cloudflare.com/ajax/libs/aplayer/1.10.1/APlayer.min.js'
7
+ export const APlayerCss =
8
+ 'https://cdnjs.cloudflare.com/ajax/libs/aplayer/1.10.1/APlayer.min.css'
9
+ export const notationJs =
10
+ 'https://cdnjs.cloudflare.com/ajax/libs/rough-notation/0.5.1/rough-notation.iife.min.js'
11
+ export const typedJs =
12
+ 'https://cdnjs.cloudflare.com/ajax/libs/typed.js/2.0.11/typed.min.js'
package/src/index.js ADDED
@@ -0,0 +1,30 @@
1
+ export * from './plugins/background'
2
+ export * from './plugins/barrage'
3
+ export * from './plugins/catalog'
4
+ export * from './plugins/charts'
5
+ export * from './plugins/clickEffects'
6
+ export * from './plugins/codeCopy'
7
+ export * from './plugins/codeHighlight'
8
+ export * from './plugins/codeLang'
9
+ export * from './plugins/codeLinenumbers'
10
+ export * from './plugins/codeTrafficLight'
11
+ export * from './plugins/colorMode'
12
+ export * from './plugins/commentsAvatars'
13
+ export * from './plugins/darkMode'
14
+ export * from './plugins/donation'
15
+ export * from './plugins/emoji'
16
+ export * from './plugins/footer'
17
+ export * from './plugins/imagePreview'
18
+ export * from './plugins/license'
19
+ export * from './plugins/live2d'
20
+ export * from './plugins/lock'
21
+ export * from './plugins/musicPlayer'
22
+ export * from './plugins/notation'
23
+ export * from './plugins/notice'
24
+ export * from './plugins/postBottomImage'
25
+ export * from './plugins/postMessage'
26
+ export * from './plugins/postTopImage'
27
+ export * from './plugins/qrcode'
28
+ export * from './plugins/signature'
29
+ export * from './plugins/tools'
30
+ export * from './plugins/webTag'
@@ -0,0 +1,50 @@
1
+ import { getBackgroundOptions } from 'tona-options'
2
+ import { isUrl, userAgent } from '../../utils/helpers'
3
+
4
+ /**
5
+ * 设置透明度
6
+ * @param {number} opacity 透明度
7
+ */
8
+ function setOpacity(opacity, opacitySelector) {
9
+ $(opacitySelector).css('opacity', `${opacity}`)
10
+ }
11
+
12
+ /**
13
+ * 设置背景
14
+ * @param {string} value
15
+ * @param {boolean} repeat 是否重复图片
16
+ */
17
+ function setBackground(value, repeat) {
18
+ const type = isUrl(value) ? 'img' : 'color'
19
+ // const type = new RegExp('http').test(value) ? 'img' : 'color'
20
+ if (type === 'color') {
21
+ $('body').css('background-color', `${value}`)
22
+ }
23
+ if (type === 'img') {
24
+ $('body').css('background-image', `url(${value})`)
25
+ if (!repeat) {
26
+ $('body').css({
27
+ 'background-repeat': 'no-repeat',
28
+ 'background-size': '100% 100%',
29
+ 'background-attachment': 'fixed',
30
+ })
31
+ if (userAgent() === 'phone') {
32
+ $('body').css('background-size', 'cover')
33
+ }
34
+ }
35
+ }
36
+ }
37
+
38
+ export function background(_, devOptions, pluginOptions) {
39
+ const { enable, opacity, value, repeat } = getBackgroundOptions(devOptions)
40
+
41
+ if (!enable) return
42
+
43
+ const { opacitySelector } = {
44
+ opacitySelector: '#main,#navigator',
45
+ ...pluginOptions,
46
+ }
47
+
48
+ setBackground(value, repeat)
49
+ setOpacity(opacity, opacitySelector)
50
+ }
File without changes
@@ -0,0 +1,104 @@
1
+ // 弹幕
2
+ import { getBarragesOptions } from 'tona-options'
3
+ import {
4
+ getClientRect,
5
+ randomColor,
6
+ randomNum,
7
+ sleep,
8
+ } from '../../utils/helpers'
9
+
10
+ /**
11
+ * @description 发送弹幕
12
+ * @param {Array} textList 弹幕列表
13
+ */
14
+ async function shootBarrage(textList, enable, opacity, colors, fontSize) {
15
+ if (!enable) {
16
+ return
17
+ }
18
+ if (!document.querySelector('#barrage-wrap')) {
19
+ $('body').append("<div id='barrage-wrap'></div>")
20
+ }
21
+
22
+ const $wrap = document.querySelector('#barrage-wrap')
23
+ const rect = getClientRect($wrap)
24
+ const wrapWidth = rect.right - rect.left
25
+ const wrapHeight = rect.bottom - rect.top
26
+
27
+ const defaultColors = [
28
+ '#FE0302',
29
+ '#FF7204',
30
+ '#FFAA02',
31
+ '#FFD302',
32
+ '#FFFF00',
33
+ '#A0EE00',
34
+ '#00CD00',
35
+ '#019899',
36
+ '#4266BE',
37
+ '#89D5FF',
38
+ '#CC0273',
39
+ '#CC0273',
40
+ ]
41
+
42
+ for (let i = 0; i < textList.length; i++) {
43
+ const text = textList[i]
44
+ const $barrage = document.createElement('span')
45
+ const barrageStyle = `left: ${wrapWidth}px;top: ${randomNum(
46
+ wrapHeight - 30,
47
+ 1,
48
+ )}px;color: ${randomColor(
49
+ colors.length ? colors : defaultColors,
50
+ )};opacity: ${opacity};font-size: ${fontSize};`
51
+
52
+ $barrage.style.cssText = barrageStyle
53
+ $barrage.textContent = text
54
+ $wrap.appendChild($barrage)
55
+
56
+ const roll = (timer) => {
57
+ const now = Date.now()
58
+ const rect = getClientRect($barrage)
59
+ let left = $barrage.offsetLeft
60
+
61
+ roll.last = roll.last || now
62
+ roll.timer = roll.timer || timer
63
+
64
+ if (left < rect.left - rect.right) {
65
+ $($barrage).remove()
66
+ } else {
67
+ if (now - roll.last >= roll.timer) {
68
+ roll.last = now
69
+ left -= 3
70
+ $barrage.style.left = `${left}px`
71
+ }
72
+ window.requestAnimationFrame(roll)
73
+ }
74
+ }
75
+
76
+ roll(randomNum(30, 1))
77
+
78
+ await sleep(1000)
79
+ }
80
+ }
81
+
82
+ export function barrage(_, devOptions) {
83
+ const { enable, opacity, colors, fontSize, barrages } =
84
+ getBarragesOptions(devOptions)
85
+
86
+ if (barrages.length) {
87
+ setTimeout(
88
+ () => shootBarrage(barrages, enable, opacity, colors, fontSize),
89
+ 3000,
90
+ )
91
+ }
92
+
93
+ // if (page === 'post' && postPageBarrages.length) {
94
+ // setTimeout(() => {
95
+ // shootBarrage(postPageBarrages, enable, opacity, colors, fontSize)
96
+ // }, 3000)
97
+ // }
98
+
99
+ // if (page === 'index' && indexBarrages.length) {
100
+ // setTimeout(() => {
101
+ // shootBarrage(indexBarrages, enable, opacity, colors, fontSize)
102
+ // }, 3000)
103
+ // }
104
+ }
@@ -0,0 +1,16 @@
1
+ #barrage-wrap {
2
+ position: fixed;
3
+ top: 90px;
4
+ width: 100vw;
5
+ height: 60vh;
6
+ text-shadow: 0px 0px 1px #000;
7
+ overflow: hidden;
8
+ z-index: 20;
9
+ pointer-events: none;
10
+
11
+ span {
12
+ position: absolute;
13
+ white-space: nowrap;
14
+ font-weight: 700;
15
+ }
16
+ }
@@ -0,0 +1,212 @@
1
+ import { getCatalogOptions } from 'tona-options'
2
+ import { getCurrentPage, hasPostTitle } from '../../utils/cnblog'
3
+ import { debounce, getClientRect, userAgent } from '../../utils/helpers'
4
+
5
+ /**
6
+ * 构建目录容器
7
+ */
8
+ function buildCatalogContainer(showTitle) {
9
+ const container = $('<nav id="catalog"></nav>')
10
+ if (showTitle) {
11
+ container.append("<h3 class='catalog-title'>目录</h3>")
12
+ }
13
+ return container
14
+ }
15
+
16
+ /**
17
+ * 构建目录列表
18
+ */
19
+ function buildCatalogList() {
20
+ const $list = $('<ul>')
21
+ const regExp = /^h[1-6]$/
22
+
23
+ // $('#cnblogs_post_body')
24
+ // .children()
25
+ $('#cnblogs_post_body :header').each(function (index) {
26
+ if (regExp.test(this.tagName.toLowerCase())) {
27
+ const className = `${this.nodeName.toLowerCase()}-list`
28
+ const mathNode = $(this).children('.math.inline')
29
+
30
+ let text
31
+ let id
32
+
33
+ if (mathNode.length) {
34
+ text =
35
+ mathNode.prop('outerHTML') +
36
+ $(this)
37
+ .contents()
38
+ .filter(function () {
39
+ return this.nodeType === 3
40
+ })
41
+ .text()
42
+ } else {
43
+ text = $(this).text()
44
+ }
45
+
46
+ if (text.length === 0) {
47
+ return
48
+ } // 如果标题为空 只有 #
49
+
50
+ if (this.id !== '') {
51
+ id = this.id
52
+ } else {
53
+ id = text.trim()
54
+ $(this).attr('id', id)
55
+ }
56
+
57
+ const title = $(
58
+ `<li class='${className}'><a href='#${id}'>${text}</a></li>`,
59
+ )
60
+ if (index === 0) {
61
+ title.addClass('catalog-active')
62
+ }
63
+ $list.append(title)
64
+ }
65
+ })
66
+ return $list
67
+ }
68
+
69
+ /**
70
+ * 构建目录
71
+ * @param {string} selector
72
+ * @param {Function} fn
73
+ */
74
+ function buildCatalog(selector, fn, showTitle) {
75
+ const container = buildCatalogContainer(showTitle)
76
+ const catalogList = buildCatalogList()
77
+ const catalog = container.append(catalogList)
78
+ $(selector)[fn]($(catalog))
79
+ }
80
+
81
+ /**
82
+ * 处理滚动事件
83
+ */
84
+ function handleScroll(scrollContainer, updateNavigation) {
85
+ $(scrollContainer).scroll(
86
+ debounce(
87
+ () => {
88
+ setActiveTitle()
89
+ autoScroll(scrollContainer, updateNavigation)
90
+ },
91
+ 50,
92
+ 1000 / 60,
93
+ ),
94
+ )
95
+ }
96
+
97
+ // TODO: 目录自动滚动
98
+ // https://stackoverflow.com/questions/61282426/fixed-sidebar-scroll-to-anchor-links-when-main-body-is-scrolled?r=SearchResults
99
+ function autoScroll(scrollContainer, updateNavigation) {
100
+ if (!updateNavigation) {
101
+ return
102
+ }
103
+ const navigation = $('#catalog')
104
+
105
+ if (scrollContainer.scrollY < 100) {
106
+ return navigation.stop().animate(
107
+ {
108
+ scrollTop: 0,
109
+ },
110
+ 800,
111
+ )
112
+ }
113
+
114
+ $('#cnblogs_post_body :header').each(function () {
115
+ const sectionName = $(this).attr('id')
116
+ const navigationMatch = $(`a[href="#${sectionName}"]`, navigation)
117
+
118
+ if (
119
+ $(this).offset().top - $(window).height() / 2 < $(window).scrollTop() &&
120
+ $(this).offset().top + $(this).height() - $(window).height() / 2 >
121
+ $(window).scrollTop()
122
+ ) {
123
+ const position = navigationMatch.position().top + navigation.scrollTop()
124
+
125
+ // TODO: Use cached selector, exit .each() when first occurrence found
126
+ return navigation.stop().animate(
127
+ {
128
+ scrollTop: position,
129
+ },
130
+ 800,
131
+ )
132
+ }
133
+ })
134
+ }
135
+
136
+ /**
137
+ * 标题动态高亮
138
+ */
139
+ function setActiveTitle() {
140
+ for (let i = $('#catalog ul li').length - 1; i >= 0; i--) {
141
+ const titleId = $($('#catalog ul li')[i])
142
+ .find('a')
143
+ .attr('href')
144
+ .replace(/#/g, '')
145
+ const postTitle = document.querySelector(
146
+ `#cnblogs_post_body [id='${titleId}']`,
147
+ )
148
+ if (getClientRect(postTitle).top <= 100) {
149
+ if ($($('#catalog ul li')[i]).hasClass('catalog-active')) {
150
+ return
151
+ }
152
+ $($('#catalog ul li')[i]).addClass('catalog-active')
153
+ $($('#catalog ul li')[i]).siblings().removeClass('catalog-active')
154
+ return
155
+ }
156
+ }
157
+ }
158
+
159
+ /**
160
+ * 目录显示隐藏
161
+ */
162
+ function toggle() {
163
+ $('.catalog-title').click(() => {
164
+ $('#catalog ul').toggle('fast', 'linear', function () {
165
+ $(this).css('display') === 'none'
166
+ ? $('.catalog-title').removeClass('is-active')
167
+ : $('.catalog-title').addClass('is-active')
168
+ })
169
+ })
170
+ }
171
+
172
+ /**
173
+ * 设置滚动条
174
+ * @param {*} showScrollbar
175
+ */
176
+ function setScrollbar(showScrollbar) {
177
+ if (!showScrollbar) {
178
+ $('#catalog').css({
179
+ overflow: 'hidden',
180
+ })
181
+ }
182
+ }
183
+
184
+ export function catalog(_, devOptions, pluginOptions = {}) {
185
+ const extraOptions = {
186
+ mountedNode: 'body',
187
+ fn: 'append',
188
+ scrollContainer: window,
189
+ updateNavigation: false,
190
+ showTitle: true,
191
+ showScrollbar: true,
192
+ }
193
+ $.extend(true, extraOptions, pluginOptions)
194
+
195
+ const { enable } = getCatalogOptions(devOptions)
196
+
197
+ if (
198
+ enable &&
199
+ hasPostTitle() &&
200
+ getCurrentPage() === 'post' &&
201
+ userAgent() === 'pc'
202
+ ) {
203
+ buildCatalog(
204
+ extraOptions.mountedNode,
205
+ extraOptions.fn,
206
+ extraOptions.showTitle,
207
+ )
208
+ handleScroll(extraOptions.scrollContainer, extraOptions.updateNavigation)
209
+ toggle()
210
+ setScrollbar(extraOptions.showScrollbar)
211
+ }
212
+ }
File without changes
@@ -0,0 +1,60 @@
1
+ import { getChartsOptions } from 'tona-options'
2
+ import { chartJs } from '../../constants/cdn'
3
+ import { loadScript } from '../../utils/helpers'
4
+
5
+ /**
6
+ * 构建图表容器
7
+ */
8
+ function createChartContainer(mountedNode) {
9
+ const container = $('<div id="chart"></div>')
10
+ const el = '<canvas id="myChart"></canvas>'
11
+ container.append(el)
12
+ $(mountedNode).append(container)
13
+ }
14
+
15
+ function createChart(labels, datasets) {
16
+ const _Chart = window.Chart
17
+
18
+ _Chart.defaults.color = '#999'
19
+
20
+ const config = {
21
+ type: 'radar',
22
+ data: {
23
+ labels,
24
+ datasets,
25
+ },
26
+ options: {
27
+ elements: {
28
+ line: {
29
+ borderWidth: 1,
30
+ },
31
+ },
32
+ plugins: {
33
+ // legend: {
34
+ // labels: {
35
+ // color: '#f00',
36
+ // },
37
+ // },
38
+ },
39
+ },
40
+ }
41
+ // eslint-disable-next-line no-new
42
+ new _Chart(document.getElementById('myChart'), config)
43
+ }
44
+
45
+ export function charts(_, devOptions, pluginOptions) {
46
+ const { enable, labels, datasets } = getChartsOptions(devOptions)
47
+ if (!enable) {
48
+ return
49
+ }
50
+
51
+ const { mountedNode } = {
52
+ mountedNode: '#sidebar_news',
53
+ ...pluginOptions,
54
+ }
55
+
56
+ loadScript(chartJs, () => {
57
+ createChartContainer(mountedNode)
58
+ createChart(labels, datasets)
59
+ })
60
+ }
@@ -0,0 +1,16 @@
1
+ @use 'sass:map';
2
+
3
+ $chart: () !default;
4
+
5
+ $chart: map.merge(
6
+ (
7
+ padding: 8px,
8
+ ),
9
+ $chart
10
+ );
11
+
12
+ $chartsPadding: map.get($chart, padding);
13
+
14
+ #chart {
15
+ padding: $chartsPadding;
16
+ }