erudit 3.0.0-dev.2 → 3.0.0-dev.20

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 (286) hide show
  1. package/app/app.vue +193 -172
  2. package/app/assets/icons/graduation.svg +3 -0
  3. package/app/components/Loading.vue +23 -23
  4. package/app/components/SiteAside.vue +393 -382
  5. package/app/components/SiteMain.vue +32 -35
  6. package/app/components/ads/Ads.vue +35 -0
  7. package/app/components/ads/AdsBannerAside.vue +61 -0
  8. package/app/components/ads/AdsBannerBottom.vue +22 -0
  9. package/app/components/ads/AdsProviderCustom.vue +35 -0
  10. package/app/components/ads/AdsProviderYandex.vue +54 -0
  11. package/app/components/ads/AdsReplacer.vue +73 -0
  12. package/app/components/aside/AsideListItem.vue +74 -74
  13. package/app/components/aside/AsideMajor.vue +56 -56
  14. package/app/components/aside/AsideMinor.vue +97 -71
  15. package/app/components/aside/major/PaneContentScroll.vue +23 -23
  16. package/app/components/aside/major/PaneSwitch.vue +54 -54
  17. package/app/components/aside/major/PaneSwitchButton.vue +63 -63
  18. package/app/components/aside/major/SiteInfo.vue +85 -85
  19. package/app/components/aside/major/panes/Language.vue +79 -79
  20. package/app/components/aside/major/panes/Pages.vue +31 -34
  21. package/app/components/aside/major/panes/Search.vue +11 -11
  22. package/app/components/aside/major/panes/nav/Nav.vue +92 -91
  23. package/app/components/aside/major/panes/nav/NavBook.vue +95 -86
  24. package/app/components/aside/major/panes/nav/NavBookLoading.vue +24 -24
  25. package/app/components/aside/major/panes/nav/NavGlobal.vue +16 -16
  26. package/app/components/aside/major/panes/nav/fnav/FNav.vue +105 -105
  27. package/app/components/aside/major/panes/nav/fnav/FNavBook.vue +32 -32
  28. package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +40 -40
  29. package/app/components/aside/major/panes/nav/fnav/FNavFolder.vue +60 -60
  30. package/app/components/aside/major/panes/nav/fnav/FNavItem.vue +34 -34
  31. package/app/components/aside/major/panes/nav/fnav/FNavSeparator.vue +80 -80
  32. package/app/components/aside/major/panes/nav/fnav/FNavTopic.vue +24 -24
  33. package/app/components/aside/major/panes/other/ItemContent.vue +29 -29
  34. package/app/components/aside/major/panes/other/ItemGenerator.vue +13 -15
  35. package/app/components/aside/major/panes/other/ItemTheme.vue +54 -54
  36. package/app/components/aside/major/panes/other/Other.vue +16 -16
  37. package/app/components/aside/minor/{Contribute.vue → AsideMinorContribute.vue} +175 -145
  38. package/app/components/aside/minor/AsideMinorNews.vue +11 -11
  39. package/app/components/aside/minor/AsideMinorPane.vue +15 -15
  40. package/app/components/aside/minor/AsideMinorTopLink.vue +67 -67
  41. package/app/components/aside/minor/content/AsideMinorContent.vue +89 -92
  42. package/app/components/aside/minor/contributor/AsideMinorContributor.vue +78 -0
  43. package/app/components/aside/minor/contributor/BookContribution.vue +64 -0
  44. package/app/components/aside/minor/topic/AsideMinorTopic.vue +29 -32
  45. package/app/components/aside/minor/topic/TopicContributors.vue +177 -177
  46. package/app/components/aside/minor/topic/TopicNav.vue +49 -49
  47. package/app/components/aside/minor/topic/TopicToc.vue +213 -203
  48. package/app/components/aside/minor/topic/TopicTocItem.vue +32 -31
  49. package/app/components/aside/utils/AsideOverlayPane.vue +40 -40
  50. package/app/components/bitran/BitranContent.vue +91 -63
  51. package/app/components/bitran/RenderWrapper.vue +10 -10
  52. package/app/components/contributor/ContributorAvatar.vue +45 -43
  53. package/app/components/contributor/ContributorListItem.vue +35 -35
  54. package/app/components/main/MainBitranContent.vue +47 -0
  55. package/app/components/main/{utils/Breadcrumb.vue → MainBreadcrumb.vue} +67 -75
  56. package/app/components/main/MainDescription.vue +24 -0
  57. package/app/components/main/MainTitle.vue +76 -0
  58. package/app/components/main/content/ContentBreadcrumb.vue +28 -0
  59. package/app/components/main/{utils → content}/ContentDecoration.vue +29 -29
  60. package/app/components/main/{utils → content}/ContentPopover.vue +188 -176
  61. package/app/components/main/{utils → content}/ContentPopovers.vue +111 -105
  62. package/app/components/main/{utils → content}/ContentReferences.vue +70 -70
  63. package/app/components/main/{utils → content}/ContentSection.vue +45 -45
  64. package/app/components/main/{utils → content}/reference/ReferenceGroup.vue +38 -38
  65. package/app/components/main/{utils → content}/reference/ReferenceItem.vue +70 -68
  66. package/app/components/main/{utils → content}/reference/ReferenceSource.vue +120 -116
  67. package/app/components/main/topic/MainTopic.vue +81 -79
  68. package/app/components/main/topic/TopicPartSwitch.vue +124 -118
  69. package/app/components/preview/Preview.vue +186 -177
  70. package/app/components/preview/PreviewDisplay.vue +139 -139
  71. package/app/components/preview/PreviewFooterAction.vue +73 -73
  72. package/app/components/preview/PreviewLoading.vue +14 -14
  73. package/app/components/preview/PreviewScreen.vue +141 -99
  74. package/app/components/preview/display/Alert.vue +50 -50
  75. package/app/components/preview/display/Custom.vue +18 -18
  76. package/app/components/preview/display/GenericLink.vue +48 -48
  77. package/app/components/preview/display/PageLink.vue +22 -20
  78. package/app/components/preview/display/Unique.vue +46 -49
  79. package/app/components/transition/Fade.vue +19 -19
  80. package/app/components/tree/TreeContainer.vue +11 -11
  81. package/app/components/tree/TreeItem.vue +89 -89
  82. package/app/composables/adsAllowed.ts +11 -0
  83. package/app/composables/bitran.ts +108 -127
  84. package/app/composables/bitranLocation.ts +7 -7
  85. package/app/composables/contentData.ts +38 -36
  86. package/app/composables/contentPage.ts +168 -156
  87. package/app/composables/contentRoute.ts +45 -45
  88. package/app/composables/darkMagic.ts +24 -24
  89. package/app/composables/externalApi.ts +69 -63
  90. package/app/composables/favicon.ts +8 -8
  91. package/app/composables/formatText.ts +99 -86
  92. package/app/composables/majorPane.ts +61 -60
  93. package/app/composables/phrases.ts +77 -80
  94. package/app/composables/theme.ts +29 -29
  95. package/app/composables/url.ts +33 -33
  96. package/app/pages/_test/preview.vue +110 -110
  97. package/app/pages/article/[...articleId].vue +3 -3
  98. package/app/pages/book/[...bookId].vue +42 -47
  99. package/app/pages/contributor/[contributorId].vue +224 -0
  100. package/app/pages/contributors.vue +183 -0
  101. package/app/pages/group/[...groupId].vue +52 -65
  102. package/app/pages/index.vue +32 -32
  103. package/app/pages/practice/[...practice].vue +3 -3
  104. package/app/pages/summary/[...summaryId].vue +3 -3
  105. package/app/plugins/analytics.ts +95 -0
  106. package/app/plugins/prerender.server.ts +22 -0
  107. package/app/public/favicon/article.svg +5 -5
  108. package/app/public/favicon/default.svg +3 -3
  109. package/app/public/favicon/practice.svg +3 -3
  110. package/app/public/favicon/summary.svg +4 -4
  111. package/app/public/logotype.svg +2 -2
  112. package/app/scripts/_immediate.js +9 -9
  113. package/app/scripts/aside/index.ts +59 -59
  114. package/app/scripts/aside/major/nav.ts +26 -26
  115. package/app/scripts/aside/minor/state.ts +37 -37
  116. package/app/scripts/aside/minor/topic.ts +3 -3
  117. package/app/scripts/flag.ts +28 -28
  118. package/app/scripts/og.ts +27 -27
  119. package/app/scripts/preview/build.ts +76 -73
  120. package/app/scripts/preview/data/alert.ts +19 -19
  121. package/app/scripts/preview/data/custom.ts +8 -8
  122. package/app/scripts/preview/data/genericLink.ts +24 -24
  123. package/app/scripts/preview/data/pageLink.ts +23 -20
  124. package/app/scripts/preview/data/unique.ts +69 -70
  125. package/app/scripts/preview/data.ts +24 -24
  126. package/app/scripts/preview/display.ts +37 -37
  127. package/app/scripts/preview/footer.ts +9 -9
  128. package/app/scripts/preview/request.ts +51 -51
  129. package/app/scripts/preview/state.ts +63 -63
  130. package/app/styles/_immediate.css +7 -7
  131. package/app/styles/_util.scss +43 -43
  132. package/app/styles/_utils.scss +44 -44
  133. package/app/styles/app.scss +91 -91
  134. package/app/styles/def/_bp.scss +27 -27
  135. package/app/styles/def/_size.scss +7 -7
  136. package/app/styles/def/_z.scss +5 -5
  137. package/app/styles/normalize.scss +49 -63
  138. package/app/styles/partials/_darkMagic.scss +5 -5
  139. package/app/styles/partials/_fnav.scss +15 -15
  140. package/app/styles/partials/_preview.scss +5 -5
  141. package/bin/erudit.mjs +2 -0
  142. package/const.ts +4 -0
  143. package/globalPath.ts +21 -21
  144. package/globals/bitran.ts +1 -47
  145. package/globals/content.ts +27 -22
  146. package/globals/contributor.ts +5 -5
  147. package/globals/erudit.ts +5 -5
  148. package/globals/register.ts +18 -18
  149. package/languages/en.ts +103 -95
  150. package/languages/ru.ts +107 -99
  151. package/module/bitran.ts +66 -34
  152. package/module/config.ts +35 -34
  153. package/module/imports.ts +67 -46
  154. package/module/index.ts +47 -47
  155. package/module/logger.ts +10 -10
  156. package/module/paths.ts +22 -22
  157. package/module/restart.ts +61 -61
  158. package/nuxt.config.ts +131 -112
  159. package/package.json +22 -15
  160. package/server/api/aside/major/nav/bookIds.ts +5 -5
  161. package/server/api/aside/major/nav/bookNav/[...bookId].ts +17 -20
  162. package/server/api/aside/major/nav/global.ts +7 -7
  163. package/server/api/aside/minor/book/[...bookId].ts +18 -0
  164. package/server/api/aside/minor/contributor/[contributorId].ts +18 -0
  165. package/server/api/aside/minor/group/[...groupId].ts +18 -0
  166. package/server/api/aside/minor/news.ts +7 -7
  167. package/server/api/aside/minor/topic.ts +36 -0
  168. package/server/api/bitran/content/[...location].ts +13 -0
  169. package/server/api/bitran/toc/[...location].ts +9 -0
  170. package/server/api/content/data.ts +75 -72
  171. package/server/api/contributor/count.ts +6 -6
  172. package/server/api/contributor/list.ts +44 -0
  173. package/server/api/contributor/page/[contributorId].ts +14 -0
  174. package/server/api/fake/content.ts +11 -11
  175. package/server/api/fake/shared/languages.ts +12 -12
  176. package/server/api/language/functions.ts +12 -12
  177. package/server/api/language/phrase/[phraseId].ts +19 -19
  178. package/server/api/language/phraseIds.ts +8 -8
  179. package/server/api/prerender.ts +19 -0
  180. package/server/api/preview/page/[...parts].ts +78 -51
  181. package/server/api/preview/unique/{[location].ts → [...location].ts} +48 -55
  182. package/server/api/problem/generator/[...path].ts +26 -0
  183. package/server/plugin/bitran/content.ts +252 -187
  184. package/server/plugin/bitran/{products → elements}/include.ts +229 -230
  185. package/server/plugin/bitran/location.ts +43 -25
  186. package/server/plugin/bitran/toc.ts +94 -83
  187. package/server/plugin/bitran/transpiler.ts +18 -46
  188. package/server/plugin/build/close.ts +12 -10
  189. package/server/plugin/build/jobs/content/builderArgs.ts +8 -8
  190. package/server/plugin/build/jobs/content/generic.ts +191 -176
  191. package/server/plugin/build/jobs/content/parse.ts +113 -100
  192. package/server/plugin/build/jobs/content/path.ts +6 -6
  193. package/server/plugin/build/jobs/content/type/book.ts +9 -9
  194. package/server/plugin/build/jobs/content/type/group.ts +37 -37
  195. package/server/plugin/build/jobs/content/type/topic.ts +36 -36
  196. package/server/plugin/build/jobs/contributors.ts +69 -66
  197. package/server/plugin/build/jobs/language.ts +36 -36
  198. package/server/plugin/build/jobs/nav.ts +345 -210
  199. package/server/plugin/build/process.ts +32 -25
  200. package/server/plugin/build/rebuild.ts +66 -55
  201. package/server/plugin/build/setup.ts +19 -21
  202. package/server/plugin/content/context.ts +119 -112
  203. package/server/plugin/db/entities/Book.ts +7 -7
  204. package/server/plugin/db/entities/Content.ts +45 -49
  205. package/server/plugin/db/entities/Contribution.ts +10 -10
  206. package/server/plugin/db/entities/Contributor.ts +25 -16
  207. package/server/plugin/db/entities/File.ts +10 -0
  208. package/server/plugin/db/entities/Group.ts +14 -14
  209. package/server/plugin/db/entities/Hash.ts +15 -15
  210. package/server/plugin/db/entities/Topic.ts +20 -20
  211. package/server/plugin/db/entities/Unique.ts +21 -21
  212. package/server/plugin/db/reset.ts +12 -0
  213. package/server/plugin/db/setup.ts +49 -34
  214. package/server/plugin/global.ts +16 -18
  215. package/server/plugin/importer.ts +16 -12
  216. package/server/plugin/index.ts +9 -9
  217. package/server/plugin/logger.ts +23 -23
  218. package/server/plugin/nav/node.ts +27 -26
  219. package/server/plugin/nav/utils.ts +179 -129
  220. package/server/plugin/repository/asideMinor.ts +51 -0
  221. package/server/plugin/repository/book.ts +39 -21
  222. package/server/plugin/repository/content.ts +240 -238
  223. package/server/plugin/repository/contentId.ts +40 -0
  224. package/server/plugin/repository/contributor.ts +98 -8
  225. package/server/plugin/repository/file.ts +10 -0
  226. package/server/plugin/repository/frontNav.ts +145 -148
  227. package/server/plugin/repository/topic.ts +35 -32
  228. package/server/tsconfig.json +9 -9
  229. package/shared/aside/minor.ts +55 -50
  230. package/shared/asset.ts +22 -15
  231. package/shared/bitran/content.ts +9 -0
  232. package/shared/bitran/contentId.ts +56 -0
  233. package/shared/bitran/toc.ts +8 -8
  234. package/shared/breadcrumb.ts +7 -0
  235. package/shared/content/bookId.ts +12 -0
  236. package/shared/content/context.ts +9 -9
  237. package/shared/content/data/base.ts +32 -32
  238. package/shared/content/data/index.ts +5 -5
  239. package/shared/content/data/type/book.ts +5 -5
  240. package/shared/content/data/type/group.ts +6 -6
  241. package/shared/content/data/type/topic.ts +11 -11
  242. package/shared/content/previousNext.ts +9 -9
  243. package/shared/contributor.ts +33 -5
  244. package/shared/frontNav.ts +41 -41
  245. package/shared/icons.ts +38 -38
  246. package/shared/image.ts +5 -5
  247. package/shared/link.ts +28 -25
  248. package/shared/popover.ts +8 -0
  249. package/shared/types/language.ts +79 -75
  250. package/shared/utils/objectsEqual.ts +4 -4
  251. package/shared/utils/stringColor.ts +9 -9
  252. package/test/contentId.test.ts +91 -0
  253. package/tsconfig.json +8 -8
  254. package/utils/contentPath.ts +67 -0
  255. package/utils/slash.ts +11 -0
  256. package/utils/stress.ts +9 -9
  257. package/app/components/ads/BannerTemplate.vue +0 -51
  258. package/app/components/ads/BottomBanner.vue +0 -45
  259. package/app/components/ads/LeftBanner.vue +0 -50
  260. package/app/components/aside/minor/AsideMinorContributor.vue +0 -5
  261. package/app/components/main/utils/ContentDescription.vue +0 -19
  262. package/app/components/main/utils/ContentFlag.vue +0 -15
  263. package/app/components/main/utils/ContentTitle.vue +0 -39
  264. package/app/composables/bitranContent.ts +0 -37
  265. package/app/pages/members.vue +0 -6
  266. package/app/styles/default.scss +0 -83
  267. package/server/api/aside/minor/path.ts +0 -78
  268. package/server/api/bitran/content/[location].ts +0 -7
  269. package/server/api/bitran/toc/[location].ts +0 -7
  270. package/server/plugin/bitran/products/link.ts +0 -116
  271. package/server/plugin/bitran/setup.ts +0 -9
  272. package/server/plugin/content/absoluteId.ts +0 -94
  273. package/shared/bitran/context.ts +0 -8
  274. package/shared/bitran/default.ts +0 -46
  275. package/shared/bitran/link/Link.vue +0 -167
  276. package/shared/bitran/link/factory.ts +0 -24
  277. package/shared/bitran/link/icon.svg +0 -3
  278. package/shared/bitran/link/languages/en.ts +0 -7
  279. package/shared/bitran/link/languages/ru.ts +0 -7
  280. package/shared/bitran/link/renderer.ts +0 -21
  281. package/shared/bitran/link/shared.ts +0 -17
  282. package/shared/bitran/link/target.ts +0 -134
  283. package/shared/bitran/link/transpiler.ts +0 -10
  284. package/shared/bitran/location.ts +0 -166
  285. package/test/bitran/link/target.test.ts +0 -141
  286. package/test/bitran/location.test.ts +0 -143
@@ -0,0 +1,91 @@
1
+ import {
2
+ toAbsoluteContentPath,
3
+ resolveContentPath,
4
+ } from '@erudit/shared/bitran/contentId';
5
+
6
+ describe('resolveContentPath', () => {
7
+ it('should handle empty paths', () => {
8
+ expect(resolveContentPath('')).toBe('');
9
+ });
10
+
11
+ it('should not change paths without special symbols', () => {
12
+ expect(resolveContentPath('foo/bar/baz')).toBe('foo/bar/baz');
13
+ });
14
+
15
+ it('should skip empty path parts', () => {
16
+ expect(resolveContentPath('/foo///bar/baz/')).toBe('foo/bar/baz');
17
+ });
18
+
19
+ it('should handle ".." parts', () => {
20
+ const testCases = [
21
+ ['foo/bar/../baz', 'foo/baz'],
22
+ ['../../../foo/bar/baz', 'foo/bar/baz'],
23
+ ['foo/../../../bar/baz', 'bar/baz'],
24
+ ['../../..', ''],
25
+ ];
26
+
27
+ for (const [input, expected] of testCases) {
28
+ expect(resolveContentPath(input!)).toBe(expected);
29
+ }
30
+ });
31
+
32
+ it('should handle "." parts', () => {
33
+ const testCases = [
34
+ ['.', ''],
35
+ ['./foo/bar/baz', 'foo/bar/baz'],
36
+ ['./foo/./bar', 'foo/bar'],
37
+ ['foo/./././bar', 'foo/bar'],
38
+ ];
39
+
40
+ for (const [input, expected] of testCases) {
41
+ expect(resolveContentPath(input!)).toBe(expected);
42
+ }
43
+ });
44
+
45
+ it('should handle paths with both "." and ".." parts', () => {
46
+ const testCases = [
47
+ ['./../.', ''],
48
+ ['foo/./../bar', 'foo/bar'],
49
+ ];
50
+
51
+ for (const [input, expected] of testCases) {
52
+ expect(resolveContentPath(input!)).toBe(expected);
53
+ }
54
+ });
55
+ });
56
+
57
+ describe('toAbsoluteContentPath', () => {
58
+ const bookIds = ['combinatorics', 'group/book'];
59
+
60
+ it('should not use context on absolute paths', () => {
61
+ expect(
62
+ toAbsoluteContentPath('/foo/bar/../baz', 'qux/vaz', bookIds),
63
+ ).toBe('foo/baz');
64
+ });
65
+
66
+ it('should fallback to absolute path if not inside book', () => {
67
+ expect(
68
+ toAbsoluteContentPath('~/foo/bar', 'unknown-book', bookIds),
69
+ ).toBe('foo/bar');
70
+ });
71
+
72
+ it('should correctly handle book-relative paths', () => {
73
+ expect(toAbsoluteContentPath('~/foo/bar', 'group/book', bookIds)).toBe(
74
+ 'group/book/foo/bar',
75
+ );
76
+ });
77
+
78
+ it('should by default append context before given content id', () => {
79
+ const testCases = [
80
+ ['baz/qux', 'foo/bar', 'foo/bar/baz/qux'],
81
+ ['./baz/qux', 'foo/bar', 'foo/bar/baz/qux'],
82
+ ['../baz/qux', 'foo/bar', 'foo/baz/qux'],
83
+ ];
84
+
85
+ for (const [contentId, context, expected] of testCases) {
86
+ expect(toAbsoluteContentPath(contentId!, context!, bookIds)).toBe(
87
+ expected,
88
+ );
89
+ }
90
+ });
91
+ });
package/tsconfig.json CHANGED
@@ -1,8 +1,8 @@
1
- {
2
- "extends": "../../playground/.erudit/nuxt/.nuxt/tsconfig.json",
3
- "compilerOptions": {
4
- "experimentalDecorators": true,
5
- "emitDecoratorMetadata": true,
6
- "types": ["@types/jest"]
7
- }
8
- }
1
+ {
2
+ "extends": "../../playground/.erudit/nuxt/.nuxt/tsconfig.json",
3
+ "compilerOptions": {
4
+ "experimentalDecorators": true,
5
+ "emitDecoratorMetadata": true,
6
+ "types": ["@types/jest"]
7
+ }
8
+ }
@@ -0,0 +1,67 @@
1
+ import { readdirSync, statSync } from 'fs';
2
+
3
+ // A directory is considered a "content directory" if it contains book, group, or topic with a file having a .js or .ts extension.
4
+ // When a directory qualifies as a content directory, its name is simplified by removing any leading digits and a '+' or '-' (e.g., "29+foo" becomes "foo").
5
+
6
+ const contentFileRegex = /^(book|group|topic)\.(js|ts)$/i;
7
+
8
+ function normalizePath(path: string): string {
9
+ return path.replace(/\\/g, '/');
10
+ }
11
+
12
+ export function isContentDirectory(directory: string): boolean {
13
+ if (!statSync(directory).isDirectory()) {
14
+ return false;
15
+ }
16
+
17
+ return readdirSync(directory).some((file) => {
18
+ return contentFileRegex.test(file);
19
+ });
20
+ }
21
+
22
+ export function getContentPath(path: string, cwd?: string): string {
23
+ path = normalizePath(path);
24
+ cwd = cwd ? normalizePath(cwd) : undefined;
25
+
26
+ const unresolvedParts = path.split('/').filter(Boolean);
27
+ const resolvedParts: string[] = [];
28
+
29
+ let currentPath = cwd || '';
30
+ while (unresolvedParts.length) {
31
+ const currentPart = unresolvedParts.shift()!;
32
+ currentPath += '/' + currentPart;
33
+ if (isContentDirectory(currentPath)) {
34
+ resolvedParts.push(currentPart.replace(/^\d+(?:\+|-)/, ''));
35
+ } else {
36
+ resolvedParts.push(currentPart);
37
+ }
38
+ }
39
+
40
+ return resolvedParts.join('/');
41
+ }
42
+
43
+ export function scanContentPaths(directory: string): Record<string, string> {
44
+ directory = normalizePath(directory);
45
+
46
+ const map: Record<string, string> = {};
47
+
48
+ function traverse(currentPath: string) {
49
+ const files = readdirSync(currentPath);
50
+
51
+ for (const file of files) {
52
+ const fullPath = currentPath + '/' + file;
53
+ const relativePath = fullPath.slice(directory.length + 1);
54
+ const stat = statSync(fullPath);
55
+
56
+ if (stat.isDirectory()) {
57
+ traverse(fullPath);
58
+ } else {
59
+ map[getContentPath(relativePath, directory)] = relativePath;
60
+ }
61
+ }
62
+ }
63
+
64
+ traverse(directory);
65
+
66
+ return map;
67
+ }
package/utils/slash.ts ADDED
@@ -0,0 +1,11 @@
1
+ export function trailingSlash(path: string, add: boolean): string {
2
+ if (path === '/') {
3
+ return '/';
4
+ }
5
+
6
+ if (add) {
7
+ return path.endsWith('/') ? path : `${path}/`;
8
+ }
9
+
10
+ return path.endsWith('/') ? path.slice(0, -1) : path;
11
+ }
package/utils/stress.ts CHANGED
@@ -1,9 +1,9 @@
1
- import chalk, { type ChalkInstance } from 'chalk';
2
-
3
- export function stress(message: string, contentChalk?: ChalkInstance) {
4
- return (
5
- chalk.dim(`'`) +
6
- (contentChalk ? contentChalk(message) : chalk.cyanBright(message)) +
7
- chalk.dim(`'`)
8
- );
9
- }
1
+ import chalk, { type ChalkInstance } from 'chalk';
2
+
3
+ export function stress(message: string, contentChalk?: ChalkInstance) {
4
+ return (
5
+ chalk.dim(`'`) +
6
+ (contentChalk ? contentChalk(message) : chalk.cyanBright(message)) +
7
+ chalk.dim(`'`)
8
+ );
9
+ }
@@ -1,51 +0,0 @@
1
- <script lang="ts" setup>
2
- const props = defineProps<{
3
- bannerId: string;
4
- }>();
5
-
6
- const { getElementId, registerBanner } = useDarkMagic();
7
- const phrase = await usePhrases('ads_replacer', '_language_code');
8
-
9
- onMounted(() => {
10
- registerBanner(props.bannerId);
11
- });
12
- </script>
13
-
14
- <template>
15
- <section :class="$style.darkMagicContainer">
16
- <div :id="getElementId(bannerId)">
17
- <div :class="$style.darkMagicReplacer">
18
- <MyIcon name="pirate" />
19
- <div v-html="phrase.ads_replacer"></div>
20
- </div>
21
- </div>
22
- </section>
23
- </template>
24
-
25
- <style lang="scss" module>
26
- .darkMagicContainer {
27
- --maxHeight: 300px;
28
-
29
- > div {
30
- width: 100%;
31
- max-height: var(--maxHeight);
32
- }
33
- }
34
-
35
- .darkMagicReplacer {
36
- max-height: var(--maxHeight);
37
- height: var(--maxHeight);
38
- width: 100%;
39
- background: var(--bgAccent);
40
- box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.1) inset;
41
- color: var(--textMuted);
42
-
43
- @include dark {
44
- box-shadow: 0px 0px 3px 1px rgba(white, 0.025) inset;
45
- }
46
-
47
- strong {
48
- color: inherit;
49
- }
50
- }
51
- </style>
@@ -1,45 +0,0 @@
1
- <script lang="ts" setup>
2
- import eruditConfig from '#erudit/config';
3
- </script>
4
-
5
- <template>
6
- <AdsBannerTemplate
7
- :bannerId="eruditConfig.ads!.bottomBlockId!"
8
- :class="$style.darkMagicBottom"
9
- />
10
- </template>
11
-
12
- <style lang="scss" module>
13
- @use '$/def/bp';
14
- @use '$/partials/darkMagic';
15
-
16
- .darkMagicBottom {
17
- --maxHeight: 300px;
18
-
19
- padding: var(--_pMainY) var(--_pMainX);
20
- padding-top: var(--gapBig);
21
-
22
- @include darkMagic.replacer {
23
- display: flex;
24
- justify-content: center;
25
- align-items: center;
26
- gap: var(--gapBig);
27
- font-size: 22px;
28
-
29
- [my-icon] {
30
- font-size: 60px;
31
- }
32
-
33
- @include bp.below('mobile') {
34
- flex-direction: column;
35
- gap: var(--gap);
36
- font-size: 16px;
37
- text-align: center;
38
-
39
- [my-icon] {
40
- font-size: 68px;
41
- }
42
- }
43
- }
44
- }
45
- </style>
@@ -1,50 +0,0 @@
1
- <script lang="ts" setup>
2
- import eruditConfig from '#erudit/config';
3
- </script>
4
-
5
- <template>
6
- <AdsBannerTemplate
7
- :bannerId="eruditConfig.ads!.leftBlockId!"
8
- :class="$style.darkMagicLeft"
9
- />
10
- </template>
11
-
12
- <style lang="scss" module>
13
- @use '$/partials/darkMagic';
14
-
15
- .darkMagicLeft {
16
- --maxHeight: 300px;
17
-
18
- padding: var(--gap);
19
- border-top: 1px solid var(--border);
20
-
21
- @media (max-height: 1080px) {
22
- --maxHeight: 200px;
23
- }
24
-
25
- @media (max-height: 700px) {
26
- --maxHeight: 100px;
27
- [my-icon] {
28
- display: none;
29
- }
30
- }
31
-
32
- @media (max-height: 350px) {
33
- display: none;
34
- }
35
-
36
- @include darkMagic.replacer {
37
- display: flex;
38
- flex-direction: column;
39
- justify-content: center;
40
- align-items: center;
41
- gap: var(--gap);
42
- text-align: center;
43
- font-size: 0.95em;
44
-
45
- [my-icon] {
46
- font-size: 46px;
47
- }
48
- }
49
- }
50
- </style>
@@ -1,5 +0,0 @@
1
- <template>
2
- <AsideMinorPane>
3
- <div>Contributor</div>
4
- </AsideMinorPane>
5
- </template>
@@ -1,19 +0,0 @@
1
- <script lang="ts" setup>
2
- defineProps<{ description: string }>();
3
- const pretty = await useFormatText();
4
- </script>
5
-
6
- <template>
7
- <section :class="$style.contentDescription">
8
- {{ pretty(description) }}
9
- </section>
10
- </template>
11
-
12
- <style lang="scss" module>
13
- .contentDescription {
14
- padding: var(--_pMainY) var(--_pMainX);
15
- font-weight: 500;
16
- font-size: 1.1em;
17
- color: var(--text);
18
- }
19
- </style>
@@ -1,15 +0,0 @@
1
- <script lang="ts" setup>
2
- import { computePosition, shift, autoUpdate, arrow } from '@floating-ui/dom';
3
-
4
- defineProps<{ icon: string; title: string }>();
5
- </script>
6
-
7
- <template>
8
- <div :class="$style.flag">Content flag</div>
9
- </template>
10
-
11
- <style lang="scss" module>
12
- .flag {
13
- color: red;
14
- }
15
- </style>
@@ -1,39 +0,0 @@
1
- <script lang="ts" setup>
2
- import { isMyIcon } from '#my-icons';
3
-
4
- defineProps<{ icon: string; title: string; hint?: string }>();
5
- </script>
6
-
7
- <template>
8
- <section :class="$style.contentTitle">
9
- <MyIcon v-if="isMyIcon(icon)" :name="icon as any" :title="hint" />
10
- <MyRuntimeIcon
11
- v-else
12
- name="content-title-icon"
13
- :svg="icon"
14
- :title="hint"
15
- />
16
- <h1>{{ title }}</h1>
17
- </section>
18
- </template>
19
-
20
- <style lang="scss" module>
21
- .contentTitle {
22
- display: flex;
23
- align-items: center;
24
- gap: var(--gap);
25
- padding: 0 var(--_pMainX);
26
-
27
- [my-icon] {
28
- font-size: 1.65em;
29
- color: var(--textMuted);
30
- position: relative;
31
- top: 1px;
32
- cursor: help;
33
- }
34
-
35
- h1 {
36
- font-size: 1.925em;
37
- }
38
- }
39
- </style>
@@ -1,37 +0,0 @@
1
- import type { ShallowRef } from 'vue';
2
- import type { BitranContent } from '@bitran-js/renderer-vue';
3
-
4
- import {
5
- encodeBitranLocation,
6
- stringifyBitranLocation,
7
- type BitranLocation,
8
- } from '@erudit/shared/bitran/location';
9
-
10
- export async function useBitranContent(
11
- location: Ref<BitranLocation | undefined>,
12
- ) {
13
- const nuxtApp = useNuxtApp();
14
- const content = shallowRef<BitranContent>();
15
-
16
- let contentPromise: Promise<ShallowRef<BitranContent>>;
17
-
18
- watchEffect(() => {
19
- if (!location.value) {
20
- // @ts-ignore
21
- contentPromise = (() => {
22
- content.value = undefined;
23
- return content;
24
- })();
25
- }
26
-
27
- const apiRoute = `/api/bitran/content/${encodeBitranLocation(stringifyBitranLocation(location.value!))}`;
28
- nuxtApp.runWithContext(() => prerenderRoutes(apiRoute));
29
- // @ts-ignore
30
- contentPromise = (async () => {
31
- content.value = (await $fetch(apiRoute)) as BitranContent;
32
- return content;
33
- })();
34
- });
35
-
36
- return contentPromise!;
37
- }
@@ -1,6 +0,0 @@
1
- <script lang="ts" setup></script>
2
-
3
- <template>
4
- <p>Members</p>
5
- <NuxtLink to="/practice/topic-b">Погнали епты!</NuxtLink>
6
- </template>
@@ -1,83 +0,0 @@
1
- @use '$/def/size';
2
-
3
- //
4
- // Vars
5
- //
6
-
7
- :root {
8
- --transitionSpeed: 200ms;
9
- --transitionFunction: cubic-bezier(0, 0, 0.5, 1);
10
- interpolate-size: allow-keywords;
11
- }
12
-
13
- // Sizes
14
-
15
- :root {
16
- --wAside: #{size.$wAside};
17
- --wMainMin: #{size.$wMainMin};
18
- --wMainMax: #{size.$wMainMax};
19
-
20
- --gap: #{size.$gap};
21
- --gapSmall: #{size.$gapSmall};
22
- --gapBig: #{size.$gapBig};
23
- }
24
-
25
- // Colors
26
-
27
- :root {
28
- --bg: light-dark(#ebebeb, #141414);
29
- --bgAside: light-dark(#f7f7f7, #1b1b1b);
30
- --bgMain: light-dark(#ffffff, #212121);
31
- --bgAccent: light-dark(#e6e6e6, #262626);
32
-
33
- --border: light-dark(#d7d7d7, #373737);
34
-
35
- --text: light-dark(#373737, #b9b9b9);
36
- --textDeep: light-dark(#232323, #e1e1e1);
37
- --textMuted: light-dark(#696969, #7f7f7f);
38
- --textDimmed: light-dark(#969696, #616161);
39
- --textDisabled: light-dark(#b9b9b9, #4f4f4f);
40
-
41
- --brand: light-dark(#1879d9, #4e94d9);
42
- --error: light-dark(#d91818, #d94e4e);
43
- --warn: light-dark(#d98718, #d9b44e);
44
- --success: light-dark(#12a512, #51a551);
45
-
46
- --scrollbar: light-dark(#bfbfbf, #494949);
47
-
48
- --invert: light-dark(black, white);
49
- }
50
-
51
- //
52
- // General rules
53
- //
54
-
55
- // Noto Sans + Noto Serif
56
- @import url('https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100..900;1,100..900&family=Noto+Serif:ital,wght@0,100..900;1,100..900&display=swap');
57
-
58
- body {
59
- background: var(--bg);
60
- font-family: 'Noto Sans', system-ui, sans-serif;
61
- color: var(--text);
62
- }
63
-
64
- h1,
65
- h2,
66
- h3,
67
- h4,
68
- h5,
69
- h6,
70
- strong {
71
- color: var(--textDeep);
72
- }
73
-
74
- ::selection {
75
- //color: var(--text);
76
- background: color-mix(in srgb, var(--brand), transparent 65%);
77
- }
78
-
79
- .icon-flip-h {
80
- [my-icon] svg {
81
- transform: scaleX(-1);
82
- }
83
- }
@@ -1,78 +0,0 @@
1
- import { isTopicPart } from 'erudit-cog/schema';
2
-
3
- import type { AsideMinorContent, AsideMinorTopic } from '@shared/aside/minor';
4
- import { getBitranToc } from '@erudit/server/plugin/bitran/toc';
5
- import {
6
- getContentContributors,
7
- getFullContentId,
8
- getPreviousNext,
9
- } from '@erudit/server/plugin/repository/content';
10
- import { getTopicPartsLinks } from '@erudit/server/plugin/repository/topic';
11
- import { locationFromPath } from '@erudit/shared/bitran/location';
12
-
13
- export default defineEventHandler(async (event) => {
14
- const query = getQuery<{ path: string }>(event);
15
-
16
- if (!query.path)
17
- throw createError({
18
- statusCode: 400,
19
- statusText: 'Missing "path" query parameter!',
20
- });
21
-
22
- const path = query.path.substring(1);
23
- const pathStart = path.split('/')[0];
24
-
25
- if (isTopicPart(pathStart)) return await createTopicData(path);
26
-
27
- if (['book', 'group'].includes(pathStart))
28
- return await createContentData(pathStart, path);
29
-
30
- return 'news';
31
- });
32
-
33
- async function createTopicData(path: string): Promise<AsideMinorTopic> {
34
- const location = locationFromPath(path);
35
-
36
- if (!location)
37
- throw createError({
38
- statusCode: 400,
39
- statusText: `Provided path "${path}" is not a valid topic location!`,
40
- });
41
-
42
- const contentId = location.path;
43
- const fullContentId = (await getFullContentId(contentId))!;
44
-
45
- const toc = await getBitranToc(location);
46
- const previousNext = await getPreviousNext(contentId);
47
- const topicPartsLinks = await getTopicPartsLinks(contentId);
48
- const contributors = await getContentContributors(contentId);
49
-
50
- return {
51
- type: 'topic',
52
- fullContentId,
53
- location,
54
- toc,
55
- nav: {
56
- ...previousNext,
57
- ...topicPartsLinks,
58
- },
59
- contributors,
60
- };
61
- }
62
-
63
- async function createContentData(
64
- type: string,
65
- path: string,
66
- ): Promise<AsideMinorContent> {
67
- const contentId = path.split('/').slice(1).join('/');
68
- const fullContentId = (await getFullContentId(contentId))!;
69
- const previousNext = await getPreviousNext(contentId);
70
- const contributors = await getContentContributors(contentId);
71
-
72
- return {
73
- type: type as any,
74
- fullContentId,
75
- nav: previousNext,
76
- contributors,
77
- };
78
- }
@@ -1,7 +0,0 @@
1
- import { parseUrlLocation } from '@server/bitran/location';
2
- import { getBitranContent } from '@server/bitran/content';
3
-
4
- export default defineEventHandler(async (event) => {
5
- const location = parseUrlLocation(getRouterParam(event, 'location') || '');
6
- return await getBitranContent(location);
7
- });
@@ -1,7 +0,0 @@
1
- import { parseUrlLocation } from '@server/bitran/location';
2
- import { getBitranToc } from '@server/bitran/toc';
3
-
4
- export default defineEventHandler(async (event) => {
5
- const location = parseUrlLocation(getRouterParam(event, 'location') || '');
6
- return await getBitranToc(location);
7
- });