valaxy 0.1.2 → 0.2.2

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 (55) hide show
  1. package/dist/chunk-2K6ROMWQ.mjs +88 -0
  2. package/dist/chunk-NBGVYWSW.js +88 -0
  3. package/dist/chunk-TSLYS2VY.js +1 -0
  4. package/dist/chunk-U4ZDCBEC.mjs +1 -0
  5. package/dist/{config-d6527c8c.d.ts → config-24b4f209.d.ts} +16 -2
  6. package/dist/index.d.ts +37 -7
  7. package/dist/index.js +1 -1
  8. package/dist/index.mjs +1 -1
  9. package/dist/node/cli.js +44 -5
  10. package/dist/node/cli.mjs +44 -5
  11. package/dist/node/index.d.ts +1 -1
  12. package/dist/node/index.js +1 -1
  13. package/dist/node/index.mjs +1 -1
  14. package/package.json +15 -13
  15. package/src/client/components/PostCard.vue +15 -16
  16. package/src/client/components/ValaxyMd.vue +1 -1
  17. package/src/client/components/ValaxySidebar.vue +0 -2
  18. package/src/client/components/ValaxyToc.vue +1 -1
  19. package/src/client/composables/category.ts +24 -5
  20. package/src/client/composables/comments/index.ts +1 -0
  21. package/src/client/composables/comments/twikoo.ts +37 -0
  22. package/src/client/composables/comments/waline.ts +0 -1
  23. package/src/client/composables/common.ts +2 -1
  24. package/src/client/composables/post.ts +26 -1
  25. package/src/client/composables/tag.ts +9 -2
  26. package/src/client/index.html +5 -0
  27. package/src/client/layouts/404.vue +5 -1
  28. package/src/client/main.ts +1 -3
  29. package/src/client/modules/valaxy.ts +3 -2
  30. package/src/client/shims.d.ts +0 -5
  31. package/src/client/styles/common/code.scss +181 -9
  32. package/src/client/styles/common/custom-blocks.scss +84 -0
  33. package/src/client/styles/common/markdown.scss +1 -4
  34. package/src/client/styles/css-vars.scss +12 -5
  35. package/src/client/styles/global/i18n.scss +20 -0
  36. package/src/client/styles/index.scss +21 -8
  37. package/src/client/styles/palette.scss +57 -48
  38. package/src/node/cli.ts +15 -0
  39. package/src/node/markdown/headings.ts +3 -2
  40. package/src/node/markdown/highlight.ts +50 -0
  41. package/src/node/markdown/highlightLines.ts +96 -0
  42. package/src/node/markdown/index.ts +20 -11
  43. package/src/node/markdown/markdown-it-container.ts +9 -1
  44. package/src/node/plugins/index.ts +1 -1
  45. package/src/node/plugins/preset.ts +2 -2
  46. package/src/node/plugins/unocss.ts +9 -12
  47. package/src/node/rss.ts +127 -0
  48. package/src/node/shims.d.ts +10 -0
  49. package/src/types/config.ts +28 -2
  50. package/src/types/posts.ts +6 -1
  51. package/dist/chunk-5D7M5SQP.js +0 -1
  52. package/dist/chunk-CF6MGLH2.mjs +0 -84
  53. package/dist/chunk-L22LX2G6.mjs +0 -1
  54. package/dist/chunk-W5MJCUNY.js +0 -84
  55. package/src/client/pages/posts/index.md +0 -5
@@ -12,8 +12,6 @@ const isHome = useLayout('home')
12
12
  <ValaxyHamburger :active="app.isSidebarOpen" class="menu-btn sidebar-toggle yun-icon-btn" :class="isHome ? '' : 'md:hidden'" @click="app.toggleSidebar()" />
13
13
 
14
14
  <aside class="va-card" :class="['sidebar', app.isSidebarOpen && 'open', !isHome && 'md:translate-x-0']">
15
- <YunSidebar />
16
- <YunConfig />
17
15
  <slot />
18
16
  </aside>
19
17
  </template>
@@ -21,7 +21,7 @@ function getStylesByLevel(level: number) {
21
21
 
22
22
  <template>
23
23
  <ul class="va-toc" p="l-4">
24
- <li v-for="header, i in headers" :key="i" :style="getStylesByLevel(header.level)">
24
+ <li v-for="header, i in headers" :key="i" class="va-toc-item" :style="getStylesByLevel(header.level)">
25
25
  <a class="toc-link-item" :href="`#${header.slug}`">{{ header.title }}</a>
26
26
  </li>
27
27
  </ul>
@@ -1,3 +1,4 @@
1
+ import { unref } from 'vue'
1
2
  import type { Post } from '../../types'
2
3
  import { usePostList } from './post'
3
4
 
@@ -20,11 +21,12 @@ export type Categories = Map<string, Category>
20
21
  * get categories from posts
21
22
  * @returns
22
23
  */
23
- export function useCategory() {
24
- const posts = usePostList()
24
+ export function useCategory(category?: string, posts: Post[] = []): ParentCategory {
25
+ if (!posts.length)
26
+ posts = unref(usePostList())
25
27
 
26
28
  const categoryMap: Category = {
27
- total: posts.value.length,
29
+ total: posts.length,
28
30
  children: new Map([
29
31
  ['Uncategorized', { total: 0, posts: [] }],
30
32
  ]),
@@ -32,7 +34,7 @@ export function useCategory() {
32
34
 
33
35
  const uncategorized = categoryMap.children.get('Uncategorized') as PostCategory
34
36
 
35
- posts.value.forEach((post: Post) => {
37
+ posts.forEach((post: Post) => {
36
38
  if (post.categories) {
37
39
  if (Array.isArray(post.categories)) {
38
40
  const len = post.categories.length
@@ -97,5 +99,22 @@ export function useCategory() {
97
99
  if (uncategorized!.total === 0)
98
100
  categoryMap.children?.delete('Uncategorized')
99
101
 
100
- return categoryMap
102
+ if (!category) {
103
+ return categoryMap
104
+ }
105
+ else {
106
+ const categoryItem = categoryMap.children.get(category)
107
+ if (categoryItem) {
108
+ return {
109
+ total: categoryItem?.total,
110
+ children: new Map([
111
+ [category, categoryItem],
112
+ ]),
113
+ }
114
+ }
115
+ else {
116
+ console.warn(`Do not have category: ${category}`)
117
+ return categoryMap
118
+ }
119
+ }
101
120
  }
@@ -1 +1,2 @@
1
+ export * from './twikoo'
1
2
  export * from './waline'
@@ -0,0 +1,37 @@
1
+ import { isClient, useScriptTag } from '@vueuse/core'
2
+ import { useI18n } from 'vue-i18n'
3
+ import { useRoute } from 'vue-router'
4
+
5
+ export function useTwikoo(options: {} = {}) {
6
+ const route = useRoute()
7
+
8
+ const { locale } = useI18n()
9
+
10
+ let twikoo: any
11
+
12
+ /**
13
+ * init waline
14
+ * @param options waline options
15
+ * @returns
16
+ */
17
+ function initTwikoo(options: {} = {}) {
18
+ if (!isClient)
19
+ return
20
+
21
+ const defaultOptions = {
22
+ el: '.comment #tcomment',
23
+ lang: locale.value,
24
+ path: route.path,
25
+ }
26
+ const twikooOptions = Object.assign(defaultOptions, options)
27
+ return window.twikoo.init(twikooOptions)
28
+ }
29
+
30
+ // 直接使用 CDN
31
+ useScriptTag('//cdn.jsdelivr.net/npm/twikoo@1.5.1/dist/twikoo.all.min.js', () => {
32
+ twikoo = initTwikoo(options)
33
+ })
34
+
35
+ // eslint-disable-next-line no-console
36
+ console.log(twikoo)
37
+ }
@@ -31,7 +31,6 @@ export function useWaline(options: {} = {}) {
31
31
  path: route.path,
32
32
  }
33
33
  const walineOptions = Object.assign(defaultOptions, options)
34
- // @ts-expect-error waline type
35
34
  return window.Waline(walineOptions)
36
35
  }
37
36
 
@@ -19,7 +19,8 @@ export function useFullUrl() {
19
19
  const config = useConfig()
20
20
  const route = useRoute()
21
21
  const url = computed(() => {
22
- const origin = config.value.url || (isClient && window.location.origin)
22
+ const siteUrl = config.value.url.endsWith('/') ? config.value.url.slice(0, -1) : config.value.url
23
+ const origin = siteUrl || (isClient && window.location.origin)
23
24
  return origin + route.path
24
25
  })
25
26
  return url
@@ -1,8 +1,18 @@
1
- import type { StyleValue } from 'vue'
1
+ import type { Ref, StyleValue } from 'vue'
2
2
  import { computed } from 'vue'
3
3
  import { useRoute, useRouter } from 'vue-router'
4
+ import { useI18n } from 'vue-i18n'
4
5
  import { useThemeConfig } from '../config'
5
6
  import { sortByDate } from '../utils'
7
+ import type { Post } from '../../types'
8
+
9
+ export const usePostTitle = (post: Ref<Post>) => {
10
+ const { locale } = useI18n()
11
+ return computed(() => {
12
+ const lang = locale.value === 'zh-CN' ? 'zh' : locale.value
13
+ return post.value[`title_${lang}`] || post.value.title
14
+ })
15
+ }
6
16
 
7
17
  /**
8
18
  * get post list
@@ -33,6 +43,21 @@ export function usePostList(params: {
33
43
  })
34
44
  }
35
45
 
46
+ /**
47
+ * get all page
48
+ * @returns
49
+ */
50
+ export function usePageList() {
51
+ const router = useRouter()
52
+ return computed(() => {
53
+ const routes = router.getRoutes()
54
+ .map((i) => {
55
+ return Object.assign({ path: i.path, excerpt: i.meta.excerpt }, i.meta.frontmatter)
56
+ })
57
+ return routes
58
+ })
59
+ }
60
+
36
61
  /**
37
62
  * get prev and next post
38
63
  * @param path
@@ -9,11 +9,18 @@ export type Tags = Map<string, {
9
9
  /**
10
10
  * get utils about tags
11
11
  */
12
- export function useTags() {
12
+ export function useTags(options: {
13
+ /**
14
+ * Primary Color
15
+ */
16
+ primary: string
17
+ } = {
18
+ primary: '#0078E7',
19
+ }) {
13
20
  const tags = useTag()
14
21
 
15
22
  const gray = new TinyColor('#999999')
16
- const primaryColor = new TinyColor(getComputedStyle(document.documentElement).getPropertyValue('--va-c-primary'))
23
+ const primaryColor = new TinyColor(options.primary)
17
24
 
18
25
  const getTagStyle = (count: number) => {
19
26
  const counts = Array.from(tags).map(([_, value]) => value.count)
@@ -1,5 +1,6 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
+
3
4
  <head>
4
5
  <meta charset="UTF-8">
5
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -14,11 +15,15 @@
14
15
  const setting = localStorage.getItem('vueuse-color-scheme') || 'auto'
15
16
  if (setting === 'dark' || (prefersDark && setting !== 'light'))
16
17
  document.documentElement.classList.toggle('dark', true)
18
+ const locale = localStorage.getItem('valaxy-locale') || 'en'
19
+ document.documentElement.setAttribute('lang', locale)
17
20
  })()
18
21
  </script>
19
22
  </head>
23
+
20
24
  <body class="font-sans">
21
25
  <div id="app"></div>
22
26
  <script type="module" src="/main.ts"></script>
23
27
  </body>
28
+
24
29
  </html>
@@ -7,7 +7,11 @@ const { t } = useI18n()
7
7
  </script>
8
8
 
9
9
  <template>
10
- <ValaxySidebar />
10
+ <ValaxySidebar>
11
+ <slot name="sidebar">
12
+ <YunSidebar />
13
+ </slot>
14
+ </ValaxySidebar>
11
15
 
12
16
  <main class="yun-main" text="center">
13
17
  <YunCard m="4" p="10" text="yellow-600">
@@ -5,14 +5,12 @@ import App from './App.vue'
5
5
 
6
6
  import '@unocss/reset/tailwind.css'
7
7
 
8
- // markdown css
9
- import 'star-markdown-css/src/scss/theme/yun.scss'
10
8
  // generate user styles
11
9
  import '/@valaxyjs/styles'
12
10
 
13
11
  import 'uno.css'
14
12
 
15
- const routes = setupLayouts(generatedRoutes)
13
+ const routes = setupLayouts(__DEV__ ? generatedRoutes : generatedRoutes.filter(i => !i.meta?.frontmatter.draft))
16
14
 
17
15
  // https://github.com/antfu/vite-ssg
18
16
  export const createApp = ViteSSG(
@@ -8,6 +8,7 @@ import { createI18n } from 'vue-i18n'
8
8
  */
9
9
  // import messages from '@intlify/vite-plugin-vue-i18n/messages'
10
10
 
11
+ import { useStorage } from '@vueuse/core'
11
12
  import { initConfig, valaxyConfigSymbol } from '../config'
12
13
 
13
14
  import type { UserModule } from '~/types'
@@ -43,12 +44,12 @@ export const install: UserModule = ({ app, router }) => {
43
44
  const config = initConfig()
44
45
  app.provide(valaxyConfigSymbol, config)
45
46
 
46
- // const {} = await import()
47
+ const locale = useStorage('valaxy-locale', config.value.lang || 'en')
47
48
 
48
49
  // init i18n, by valaxy config
49
50
  const i18n = createI18n({
50
51
  legacy: false,
51
- locale: config.value.lang || 'en',
52
+ locale: locale.value,
52
53
  messages,
53
54
  })
54
55
  app.use(i18n)
@@ -3,11 +3,6 @@ import 'vue-router'
3
3
  import type { Post } from 'valaxy'
4
4
  import type { Header } from '../node/markdown'
5
5
 
6
- declare interface Window {
7
- // extend the window
8
- Waline: any
9
- }
10
-
11
6
  // with vite-plugin-md, markdowns can be treat as Vue components
12
7
  declare module '*.md' {
13
8
  import type { DefineComponent } from 'vue'
@@ -1,5 +1,73 @@
1
+ @use "~/styles/mixins" as *;
2
+
3
+ /* https://github.com/antfu/prism-theme-vars */
4
+ @use "prism-theme-vars/base.css" as *;
5
+
6
+ @include mobile {
7
+ .markdown-body {
8
+ div[class*="language-"] {
9
+ margin: 0 -1rem;
10
+ }
11
+ }
12
+ }
13
+
14
+ .markdown-body {
15
+ div[class*="language-"] {
16
+ position: relative;
17
+ padding: 0;
18
+ background-color: var(--smc-code-bg-color);
19
+
20
+ pre {
21
+ position: relative;
22
+ padding: 1rem;
23
+ z-index: 1;
24
+ background: none;
25
+
26
+ // expand
27
+ code {
28
+ display: block;
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+ /* Line highlighting */
35
+
36
+ .highlight-lines {
37
+ position: absolute;
38
+ top: 0;
39
+ bottom: 0;
40
+ left: 0;
41
+ padding: 1rem 0;
42
+ width: 100%;
43
+ line-height: var(--prism-line-height);
44
+ user-select: none;
45
+ overflow: hidden;
46
+
47
+ .highlighted {
48
+ background-color: rgba(0, 0, 0, 0.08);
49
+ }
50
+ }
51
+
52
+ .dark {
53
+ .highlight-lines {
54
+ .highlighted {
55
+ background-color: rgba(0, 0, 0, 0.4);
56
+ }
57
+ }
58
+ }
59
+
60
+ .markdown-body {
61
+ code {
62
+ color: var(--prism-foreground) !important;
63
+ }
64
+ }
65
+
66
+ // prism
1
67
  html:not(.dark) {
2
- --prism-foreground: #393a34;
68
+ // text
69
+ --prism-foreground: #224466;
70
+
3
71
  --prism-background: #f8f8f8;
4
72
  --prism-comment: #758575;
5
73
  --prism-namespace: #444444;
@@ -7,7 +75,7 @@ html:not(.dark) {
7
75
  --prism-punctuation: #80817d;
8
76
  --prism-literal: #36acaa;
9
77
  --prism-keyword: #248459;
10
- --prism-function: #4D9375;
78
+ --prism-function: #0088bb;
11
79
  --prism-deleted: #9a050f;
12
80
  --prism-class: #2b91af;
13
81
  --prism-builtin: #800000;
@@ -16,20 +84,124 @@ html:not(.dark) {
16
84
  }
17
85
 
18
86
  html.dark {
19
- --prism-foreground: #A6ACCD;
87
+ --prism-foreground: #a6accd;
88
+
20
89
  --prism-background: #242424;
21
90
  --prism-namespace: #aaaaaa;
22
91
  --prism-comment: #758575;
23
92
  --prism-namespace: #444444;
24
- --prism-string: #C3E88D;
25
- --prism-punctuation: #A6ACCD;
93
+ --prism-string: #c3e88d;
94
+ --prism-punctuation: #a6accd;
26
95
  --prism-literal: #36acaa;
27
- --prism-keyword: #89DDFF;
28
- --prism-function: #82AAFF;
96
+ --prism-keyword: #89ddff;
97
+ --prism-function: #82aaff;
29
98
  --prism-deleted: #9a050f;
30
99
  --prism-class: #4ec9b0;
31
100
  --prism-builtin: #d16969;
32
- --prism-property: #C792EA;
101
+ --prism-property: #c792ea;
33
102
  --prism-regex: #ad502b;
34
- --prism-selector: #C3E88D;
103
+ --prism-selector: #c3e88d;
104
+ }
105
+
106
+ /* Language marker */
107
+ // @use 'prism-theme-vars/marker.css' as *; * not div
108
+ div[class*="language-"]:before {
109
+ position: absolute;
110
+ top: 0.6em;
111
+ right: 1em;
112
+ z-index: 2;
113
+ font-size: 0.8rem;
114
+ color: #888;
115
+ }
116
+
117
+ div[class~="language-html"]:before,
118
+ div[class~="language-markup"]:before {
119
+ content: "html";
120
+ }
121
+
122
+ div[class~="language-md"]:before,
123
+ div[class~="language-markdown"]:before {
124
+ content: "md";
125
+ }
126
+
127
+ div[class~="language-css"]:before {
128
+ content: "css";
129
+ }
130
+
131
+ div[class~="language-sass"]:before {
132
+ content: "sass";
133
+ }
134
+
135
+ div[class~="language-scss"]:before {
136
+ content: "scss";
137
+ }
138
+
139
+ div[class~="language-less"]:before {
140
+ content: "less";
141
+ }
142
+
143
+ div[class~="language-stylus"]:before {
144
+ content: "styl";
145
+ }
146
+
147
+ div[class~="language-js"]:before,
148
+ div[class~="language-javascript"]:before {
149
+ content: "js";
150
+ }
151
+
152
+ div[class~="language-ts"]:before,
153
+ div[class~="language-typescript"]:before {
154
+ content: "ts";
155
+ }
156
+
157
+ div[class~="language-json"]:before {
158
+ content: "json";
159
+ }
160
+
161
+ div[class~="language-rb"]:before,
162
+ div[class~="language-ruby"]:before {
163
+ content: "rb";
164
+ }
165
+
166
+ div[class~="language-py"]:before,
167
+ div[class~="language-python"]:before {
168
+ content: "py";
169
+ }
170
+
171
+ div[class~="language-sh"]:before,
172
+ div[class~="language-bash"]:before {
173
+ content: "sh";
174
+ }
175
+
176
+ div[class~="language-php"]:before {
177
+ content: "php";
178
+ }
179
+
180
+ div[class~="language-go"]:before {
181
+ content: "go";
182
+ }
183
+
184
+ div[class~="language-rust"]:before {
185
+ content: "rust";
186
+ }
187
+
188
+ div[class~="language-java"]:before {
189
+ content: "java";
190
+ }
191
+
192
+ div[class~="language-c"]:before {
193
+ content: "c";
194
+ }
195
+
196
+ div[class~="language-yml"]:before,
197
+ div[class~="language-yaml"]:before {
198
+ content: "yaml";
199
+ }
200
+
201
+ div[class~="language-dockerfile"]:before {
202
+ content: "dockerfile";
203
+ }
204
+
205
+ div[class~="language-vue"]:before {
206
+ content: "vue";
35
207
  }
@@ -0,0 +1,84 @@
1
+ .custom-block.tip,
2
+ .custom-block.info,
3
+ .custom-block.warning,
4
+ .custom-block.danger {
5
+ margin: 1rem 0;
6
+ border-left: 6px solid;
7
+ padding: 0.1rem 1.5rem;
8
+ overflow-x: auto;
9
+ }
10
+
11
+ :root {
12
+ --va-c-text-warning: #544500;
13
+ }
14
+
15
+ html.dark {
16
+ --va-c-text-warning: #ffea8a;
17
+ }
18
+
19
+ .custom-block {
20
+ &.info {
21
+ background-color: rgba(200, 200, 200, 0.1);
22
+ }
23
+ &.tip {
24
+ background-color: rgba(200, 200, 200, 0.1);
25
+ border-color: var(--va-c-primary);
26
+ }
27
+
28
+ &.warning {
29
+ border-color: #e7c000;
30
+ color: var(--va-c-text-warning);
31
+ background-color: rgba(255, 229, 100, 0.3);
32
+
33
+ a {
34
+ color: var(--va-c-text);
35
+ }
36
+ }
37
+ }
38
+
39
+ .custom-block.info {
40
+ border-color: var(--c-text-light-2);
41
+ }
42
+
43
+ .custom-block.warning .custom-block-title {
44
+ color: #b29400;
45
+ }
46
+
47
+ .custom-block.danger {
48
+ border-color: #c00;
49
+ color: #4d0000;
50
+ background-color: #ffe6e6;
51
+ }
52
+
53
+ .custom-block.danger .custom-block-title {
54
+ color: #900;
55
+ }
56
+
57
+ .custom-block.details {
58
+ position: relative;
59
+ display: block;
60
+ border-radius: 2px;
61
+ margin: 1.6em 0;
62
+ padding: 1.6em;
63
+ background-color: rgba(200, 200, 200, 0.2);
64
+ }
65
+
66
+ .custom-block.details h4 {
67
+ margin-top: 0;
68
+ }
69
+
70
+ .custom-block.details figure:last-child,
71
+ .custom-block.details p:last-child {
72
+ margin-bottom: 0;
73
+ padding-bottom: 0;
74
+ }
75
+
76
+ .custom-block.details summary {
77
+ outline: none;
78
+ cursor: pointer;
79
+ }
80
+
81
+ .custom-block-title {
82
+ margin-bottom: -0.4rem;
83
+ font-weight: 600;
84
+ }
@@ -1,11 +1,8 @@
1
- /* https://github.com/antfu/prism-theme-vars */
2
- @use 'prism-theme-vars/base.css' as *;
3
- @use './code.scss' as *;
1
+ @use 'sass:map';
4
2
 
5
3
  .markdown-body {
6
4
  --prism-font-family: var(--va-font-mono);
7
5
 
8
- --smc-link-color: var(--va-c-link);
9
6
  --smc-font-family: var(--va-font-sans);
10
7
  }
11
8
 
@@ -1,7 +1,14 @@
1
1
  @use "sass:map";
2
2
  @use "./mixins" as *;
3
3
  @use "./vars" as *;
4
- @use "./palette" as *;
4
+
5
+ $c-primary: #0078E7 !default;
6
+
7
+ @use "./palette" with (
8
+ $colors: (
9
+ 'primary': $c-primary,
10
+ )
11
+ );
5
12
 
6
13
  // common
7
14
  :root {
@@ -14,19 +21,19 @@
14
21
  // colors
15
22
  :root {
16
23
  // palette different with colors
17
- @include set-css-var-from-map($palette, 'c');
24
+ @include set-css-var-from-map(palette.$palette, 'c');
18
25
  // primary
19
- @include set-css-var-from-map($colors, 'c');
26
+ @include set-css-var-from-map(palette.$colors, 'c');
20
27
  }
21
28
 
22
29
  // light
23
30
  :root {
24
31
  color-scheme: light;
25
- @include set-css-var-from-map($light);
32
+ @include set-css-var-from-map(palette.$light);
26
33
  }
27
34
 
28
35
  // dark
29
36
  html.dark {
30
37
  color-scheme: dark;
31
- @include set-css-var-from-map($dark);
38
+ @include set-css-var-from-map(palette.$dark);
32
39
  }
@@ -0,0 +1,20 @@
1
+ $languages: zh-CN, en;
2
+
3
+ html[lang] {
4
+ .markdown-body {
5
+ div[lang] {
6
+ display: none;
7
+ }
8
+ }
9
+ }
10
+
11
+ @each $lang in $languages {
12
+ html[lang="#{$lang}"] {
13
+ // only for markdown
14
+ .markdown-body {
15
+ div[lang="#{$lang}"] {
16
+ display: block;
17
+ }
18
+ }
19
+ }
20
+ }