erudit 2.0.0-dev.7
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.
- package/.nuxtrc +1 -0
- package/app/app.vue +172 -0
- package/app/assets/icons/alert.svg +3 -0
- package/app/assets/icons/angle-right.svg +3 -0
- package/app/assets/icons/arrow-in-text.svg +3 -0
- package/app/assets/icons/arrow-left.svg +3 -0
- package/app/assets/icons/arrow-up-to-right.svg +3 -0
- package/app/assets/icons/aside-open.svg +3 -0
- package/app/assets/icons/asterisk.svg +3 -0
- package/app/assets/icons/book-question.svg +3 -0
- package/app/assets/icons/book.svg +3 -0
- package/app/assets/icons/bug.svg +3 -0
- package/app/assets/icons/chip.svg +3 -0
- package/app/assets/icons/circle-help.svg +3 -0
- package/app/assets/icons/construction.svg +3 -0
- package/app/assets/icons/cross.svg +3 -0
- package/app/assets/icons/draw.svg +3 -0
- package/app/assets/icons/ellipsis-vertical.svg +3 -0
- package/app/assets/icons/file-check.svg +3 -0
- package/app/assets/icons/file-lines.svg +3 -0
- package/app/assets/icons/file-star.svg +3 -0
- package/app/assets/icons/folder-open.svg +3 -0
- package/app/assets/icons/folder.svg +3 -0
- package/app/assets/icons/globe.svg +3 -0
- package/app/assets/icons/house.svg +3 -0
- package/app/assets/icons/link-external.svg +3 -0
- package/app/assets/icons/link.svg +3 -0
- package/app/assets/icons/moon.svg +3 -0
- package/app/assets/icons/outline/book.svg +3 -0
- package/app/assets/icons/outline/file-lines.svg +3 -0
- package/app/assets/icons/pirate.svg +3 -0
- package/app/assets/icons/plus-circle.svg +3 -0
- package/app/assets/icons/plus.svg +3 -0
- package/app/assets/icons/puzzle.svg +3 -0
- package/app/assets/icons/search.svg +3 -0
- package/app/assets/icons/shuffle.svg +3 -0
- package/app/assets/icons/star.svg +3 -0
- package/app/assets/icons/sun-moon.svg +3 -0
- package/app/assets/icons/sun.svg +3 -0
- package/app/assets/icons/user.svg +3 -0
- package/app/assets/icons/users.svg +3 -0
- package/app/components/Loading.vue +23 -0
- package/app/components/SiteAside.vue +382 -0
- package/app/components/SiteMain.vue +35 -0
- package/app/components/ads/BannerTemplate.vue +51 -0
- package/app/components/ads/BottomBanner.vue +45 -0
- package/app/components/ads/LeftBanner.vue +50 -0
- package/app/components/aside/AsideListItem.vue +74 -0
- package/app/components/aside/AsideMajor.vue +56 -0
- package/app/components/aside/AsideMinor.vue +71 -0
- package/app/components/aside/major/PaneContentScroll.vue +23 -0
- package/app/components/aside/major/PaneSwitch.vue +54 -0
- package/app/components/aside/major/PaneSwitchButton.vue +63 -0
- package/app/components/aside/major/SiteInfo.vue +85 -0
- package/app/components/aside/major/panes/Language.vue +79 -0
- package/app/components/aside/major/panes/Pages.vue +34 -0
- package/app/components/aside/major/panes/Search.vue +3 -0
- package/app/components/aside/major/panes/nav/Nav.vue +91 -0
- package/app/components/aside/major/panes/nav/NavBook.vue +86 -0
- package/app/components/aside/major/panes/nav/NavBookLoading.vue +24 -0
- package/app/components/aside/major/panes/nav/NavGlobal.vue +16 -0
- package/app/components/aside/major/panes/nav/fnav/FNav.vue +105 -0
- package/app/components/aside/major/panes/nav/fnav/FNavBook.vue +32 -0
- package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +40 -0
- package/app/components/aside/major/panes/nav/fnav/FNavFolder.vue +60 -0
- package/app/components/aside/major/panes/nav/fnav/FNavItem.vue +34 -0
- package/app/components/aside/major/panes/nav/fnav/FNavSeparator.vue +80 -0
- package/app/components/aside/major/panes/nav/fnav/FNavTopic.vue +24 -0
- package/app/components/aside/major/panes/other/ItemContent.vue +29 -0
- package/app/components/aside/major/panes/other/ItemGenerator.vue +15 -0
- package/app/components/aside/major/panes/other/ItemTheme.vue +54 -0
- package/app/components/aside/major/panes/other/Other.vue +16 -0
- package/app/components/aside/minor/AsideMinorContributor.vue +5 -0
- package/app/components/aside/minor/AsideMinorNews.vue +11 -0
- package/app/components/aside/minor/AsideMinorPane.vue +16 -0
- package/app/components/aside/minor/AsideMinorTopLink.vue +67 -0
- package/app/components/aside/minor/Contribute.vue +145 -0
- package/app/components/aside/minor/content/AsideMinorContent.vue +92 -0
- package/app/components/aside/minor/topic/AsideMinorTopic.vue +32 -0
- package/app/components/aside/minor/topic/TopicContributors.vue +177 -0
- package/app/components/aside/minor/topic/TopicNav.vue +49 -0
- package/app/components/aside/minor/topic/TopicToc.vue +202 -0
- package/app/components/aside/minor/topic/TopicTocItem.vue +31 -0
- package/app/components/aside/utils/AsideOverlayPane.vue +40 -0
- package/app/components/bitran/BitranContent.vue +64 -0
- package/app/components/bitran/RenderWrapper.vue +12 -0
- package/app/components/contributor/ContributorAvatar.vue +43 -0
- package/app/components/contributor/ContributorListItem.vue +35 -0
- package/app/components/main/topic/MainTopic.vue +79 -0
- package/app/components/main/topic/TopicPartSwitch.vue +118 -0
- package/app/components/main/utils/Breadcrumb.vue +75 -0
- package/app/components/main/utils/ContentDecoration.vue +29 -0
- package/app/components/main/utils/ContentDescription.vue +20 -0
- package/app/components/main/utils/ContentFlag.vue +16 -0
- package/app/components/main/utils/ContentPopover.vue +176 -0
- package/app/components/main/utils/ContentPopovers.vue +105 -0
- package/app/components/main/utils/ContentReferences.vue +76 -0
- package/app/components/main/utils/ContentSection.vue +42 -0
- package/app/components/main/utils/ContentTitle.vue +37 -0
- package/app/components/main/utils/reference/ReferenceGroup.vue +41 -0
- package/app/components/main/utils/reference/ReferenceItem.vue +64 -0
- package/app/components/main/utils/reference/ReferenceSource.vue +110 -0
- package/app/components/preview/Preview.vue +177 -0
- package/app/components/preview/PreviewDisplay.vue +139 -0
- package/app/components/preview/PreviewFooterAction.vue +73 -0
- package/app/components/preview/PreviewLoading.vue +15 -0
- package/app/components/preview/PreviewScreen.vue +99 -0
- package/app/components/preview/display/Alert.vue +50 -0
- package/app/components/preview/display/Custom.vue +18 -0
- package/app/components/preview/display/GenericLink.vue +48 -0
- package/app/components/preview/display/PageLink.vue +20 -0
- package/app/components/preview/display/Unique.vue +49 -0
- package/app/components/transition/Fade.vue +22 -0
- package/app/components/tree/TreeContainer.vue +12 -0
- package/app/components/tree/TreeItem.vue +89 -0
- package/app/composables/bitran.ts +132 -0
- package/app/composables/bitranContent.ts +36 -0
- package/app/composables/bitranLocation.ts +7 -0
- package/app/composables/contentData.ts +36 -0
- package/app/composables/contentPage.ts +156 -0
- package/app/composables/contentRoute.ts +45 -0
- package/app/composables/darkMagic.ts +24 -0
- package/app/composables/externalApi.ts +63 -0
- package/app/composables/favicon.ts +8 -0
- package/app/composables/formatText.ts +86 -0
- package/app/composables/majorPane.ts +60 -0
- package/app/composables/phrases.ts +80 -0
- package/app/composables/theme.ts +29 -0
- package/app/composables/url.ts +33 -0
- package/app/pages/_test/preview.vue +110 -0
- package/app/pages/article/[...articleId].vue +3 -0
- package/app/pages/book/[...bookId].vue +47 -0
- package/app/pages/group/[...groupId].vue +64 -0
- package/app/pages/index.vue +32 -0
- package/app/pages/members.vue +7 -0
- package/app/pages/practice/[...practice].vue +3 -0
- package/app/pages/summary/[...summaryId].vue +3 -0
- package/app/public/favicon/article.svg +10 -0
- package/app/public/favicon/default.svg +10 -0
- package/app/public/favicon/practice.svg +10 -0
- package/app/public/favicon/summary.svg +10 -0
- package/app/public/logotype.svg +17 -0
- package/app/public/og-default.png +0 -0
- package/app/public/user.svg +10 -0
- package/app/scripts/_immediate.js +4 -0
- package/app/scripts/aside/index.ts +59 -0
- package/app/scripts/aside/major/nav.ts +26 -0
- package/app/scripts/aside/minor/state.ts +37 -0
- package/app/scripts/aside/minor/topic.ts +3 -0
- package/app/scripts/flag.ts +28 -0
- package/app/scripts/og.ts +27 -0
- package/app/scripts/preview/build.ts +84 -0
- package/app/scripts/preview/data/alert.ts +19 -0
- package/app/scripts/preview/data/custom.ts +8 -0
- package/app/scripts/preview/data/genericLink.ts +24 -0
- package/app/scripts/preview/data/pageLink.ts +20 -0
- package/app/scripts/preview/data/unique.ts +70 -0
- package/app/scripts/preview/data.ts +26 -0
- package/app/scripts/preview/display.ts +39 -0
- package/app/scripts/preview/footer.ts +9 -0
- package/app/scripts/preview/request.ts +51 -0
- package/app/scripts/preview/state.ts +63 -0
- package/app/styles/_immediate.css +3 -0
- package/app/styles/_util.scss +50 -0
- package/app/styles/_utils.scss +44 -0
- package/app/styles/app.scss +91 -0
- package/app/styles/def/_bp.scss +24 -0
- package/app/styles/def/_size.scss +7 -0
- package/app/styles/def/_z.scss +5 -0
- package/app/styles/default.scss +85 -0
- package/app/styles/normalize.scss +63 -0
- package/app/styles/partials/_darkMagic.scss +7 -0
- package/app/styles/partials/_fnav.scss +18 -0
- package/app/styles/partials/_preview.scss +7 -0
- package/globalPath.ts +24 -0
- package/globals/bitran.ts +39 -0
- package/globals/content.ts +22 -0
- package/globals/contributor.ts +5 -0
- package/globals/erudit.ts +5 -0
- package/globals/register.ts +18 -0
- package/languages/en.ts +95 -0
- package/languages/ru.ts +99 -0
- package/module/bitran.ts +34 -0
- package/module/config.ts +34 -0
- package/module/imports.ts +46 -0
- package/module/index.ts +35 -0
- package/module/logger.ts +10 -0
- package/module/paths.ts +22 -0
- package/module/restart.ts +61 -0
- package/nuxt.config.ts +96 -0
- package/package.json +32 -0
- package/server/api/aside/major/nav/bookIds.ts +5 -0
- package/server/api/aside/major/nav/bookNav/[...bookId].ts +20 -0
- package/server/api/aside/major/nav/global.ts +7 -0
- package/server/api/aside/minor/news.ts +7 -0
- package/server/api/aside/minor/path.ts +78 -0
- package/server/api/bitran/content/[location].ts +7 -0
- package/server/api/bitran/toc/[location].ts +7 -0
- package/server/api/content/data.ts +72 -0
- package/server/api/contributor/count.ts +6 -0
- package/server/api/fake/content.ts +11 -0
- package/server/api/fake/shared/languages.ts +12 -0
- package/server/api/language/functions.ts +12 -0
- package/server/api/language/phrase/[phraseId].ts +19 -0
- package/server/api/language/phraseIds.ts +8 -0
- package/server/api/preview/page/[...parts].ts +51 -0
- package/server/api/preview/unique/[location].ts +55 -0
- package/server/plugin/bitran/content.ts +176 -0
- package/server/plugin/bitran/core.ts +51 -0
- package/server/plugin/bitran/location.ts +25 -0
- package/server/plugin/bitran/products/include.ts +229 -0
- package/server/plugin/bitran/products/link.ts +114 -0
- package/server/plugin/bitran/setup.ts +10 -0
- package/server/plugin/bitran/toc.ts +82 -0
- package/server/plugin/build/close.ts +10 -0
- package/server/plugin/build/jobs/content/builderArgs.ts +8 -0
- package/server/plugin/build/jobs/content/generic.ts +176 -0
- package/server/plugin/build/jobs/content/parse.ts +90 -0
- package/server/plugin/build/jobs/content/path.ts +6 -0
- package/server/plugin/build/jobs/content/type/book.ts +9 -0
- package/server/plugin/build/jobs/content/type/group.ts +37 -0
- package/server/plugin/build/jobs/content/type/topic.ts +36 -0
- package/server/plugin/build/jobs/contributors.ts +66 -0
- package/server/plugin/build/jobs/language.ts +36 -0
- package/server/plugin/build/jobs/nav.ts +209 -0
- package/server/plugin/build/process.ts +25 -0
- package/server/plugin/build/rebuild.ts +55 -0
- package/server/plugin/build/setup.ts +21 -0
- package/server/plugin/content/absoluteId.ts +94 -0
- package/server/plugin/content/context.ts +112 -0
- package/server/plugin/db/entities/Book.ts +7 -0
- package/server/plugin/db/entities/Content.ts +49 -0
- package/server/plugin/db/entities/Contribution.ts +10 -0
- package/server/plugin/db/entities/Contributor.ts +16 -0
- package/server/plugin/db/entities/Group.ts +14 -0
- package/server/plugin/db/entities/Hash.ts +15 -0
- package/server/plugin/db/entities/Topic.ts +20 -0
- package/server/plugin/db/entities/Unique.ts +21 -0
- package/server/plugin/db/setup.ts +34 -0
- package/server/plugin/global.ts +18 -0
- package/server/plugin/importer.ts +12 -0
- package/server/plugin/index.ts +9 -0
- package/server/plugin/logger.ts +23 -0
- package/server/plugin/nav/node.ts +26 -0
- package/server/plugin/nav/utils.ts +129 -0
- package/server/plugin/repository/book.ts +21 -0
- package/server/plugin/repository/content.ts +238 -0
- package/server/plugin/repository/contributor.ts +8 -0
- package/server/plugin/repository/frontNav.ts +148 -0
- package/server/plugin/repository/topic.ts +32 -0
- package/server/tsconfig.json +7 -0
- package/shared/aside/minor.ts +50 -0
- package/shared/asset.ts +15 -0
- package/shared/bitran/alias.ts +17 -0
- package/shared/bitran/context.ts +7 -0
- package/shared/bitran/location.ts +166 -0
- package/shared/bitran/products/alias/core/factory.ts +46 -0
- package/shared/bitran/products/alias/core/index.ts +13 -0
- package/shared/bitran/products/alias/render/Alias.vue +10 -0
- package/shared/bitran/products/alias/render/icon.svg +3 -0
- package/shared/bitran/products/alias/render/index.ts +17 -0
- package/shared/bitran/products/alias/render/languages/en.ts +5 -0
- package/shared/bitran/products/alias/render/languages/ru.ts +5 -0
- package/shared/bitran/products/alias/shared.ts +11 -0
- package/shared/bitran/products/heading/core/factory.ts +53 -0
- package/shared/bitran/products/heading/core/index.ts +19 -0
- package/shared/bitran/products/heading/render/Heading.vue +47 -0
- package/shared/bitran/products/heading/render/icon.svg +3 -0
- package/shared/bitran/products/heading/render/index.ts +17 -0
- package/shared/bitran/products/heading/render/languages/en.ts +5 -0
- package/shared/bitran/products/heading/render/languages/ru.ts +5 -0
- package/shared/bitran/products/heading/shared.ts +13 -0
- package/shared/bitran/products/include/core/factory.ts +61 -0
- package/shared/bitran/products/include/core/index.ts +13 -0
- package/shared/bitran/products/include/render/Include.vue +13 -0
- package/shared/bitran/products/include/render/icon.svg +3 -0
- package/shared/bitran/products/include/render/index.ts +18 -0
- package/shared/bitran/products/include/render/languages/en.ts +5 -0
- package/shared/bitran/products/include/render/languages/ru.ts +5 -0
- package/shared/bitran/products/include/shared.ts +15 -0
- package/shared/bitran/products/link/core/factory.ts +20 -0
- package/shared/bitran/products/link/core/index.ts +17 -0
- package/shared/bitran/products/link/render/Link.vue +174 -0
- package/shared/bitran/products/link/render/icon.svg +3 -0
- package/shared/bitran/products/link/render/index.ts +17 -0
- package/shared/bitran/products/link/render/languages/en.ts +5 -0
- package/shared/bitran/products/link/render/languages/ru.ts +5 -0
- package/shared/bitran/products/link/shared.ts +15 -0
- package/shared/bitran/products/link/target.ts +134 -0
- package/shared/bitran/toc.ts +8 -0
- package/shared/content/context.ts +9 -0
- package/shared/content/data/base.ts +32 -0
- package/shared/content/data/index.ts +5 -0
- package/shared/content/data/type/book.ts +5 -0
- package/shared/content/data/type/group.ts +6 -0
- package/shared/content/data/type/topic.ts +11 -0
- package/shared/content/previousNext.ts +9 -0
- package/shared/contributor.ts +5 -0
- package/shared/frontNav.ts +41 -0
- package/shared/icons.ts +38 -0
- package/shared/image.ts +5 -0
- package/shared/link.ts +25 -0
- package/shared/types/language.ts +75 -0
- package/shared/utils/objectsEqual.ts +4 -0
- package/shared/utils/stringColor.ts +9 -0
- package/test/bitran/alias.test.ts +44 -0
- package/test/bitran/location.test.ts +143 -0
- package/test/bitran/products/alias.test.ts +83 -0
- package/test/bitran/products/heading.test.ts +119 -0
- package/test/bitran/products/include.test.ts +77 -0
- package/test/bitran/products/link/factory.test.ts +30 -0
- package/test/bitran/products/link/target.test.ts +138 -0
- package/tsconfig.json +8 -0
- package/utils/stress.ts +9 -0
package/module/bitran.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { addTemplate } from 'nuxt/kit';
|
|
2
|
+
import type { Nuxt } from 'nuxt/schema';
|
|
3
|
+
|
|
4
|
+
import { eruditEndNuxtPath, projectPath } from '@erudit/globalPath';
|
|
5
|
+
import type { EruditBitranConfig } from '@erudit/globals/bitran';
|
|
6
|
+
import { logger } from '@erudit/module/logger';
|
|
7
|
+
|
|
8
|
+
export async function setupBitranConfig(_nuxt: Nuxt) {
|
|
9
|
+
let config: Partial<EruditBitranConfig>;
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
const projectConfig = (await import(projectPath('bitran'))).default;
|
|
13
|
+
if (!projectConfig) throw new Error('Falsy Bitran config!');
|
|
14
|
+
config = projectConfig;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
logger.warn(`Failed to load Bitran config!\n\n${error}`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const templateFilename = '#erudit/client/bitran.ts';
|
|
20
|
+
|
|
21
|
+
addTemplate({
|
|
22
|
+
filename: templateFilename,
|
|
23
|
+
write: true,
|
|
24
|
+
getContents: () => `
|
|
25
|
+
${config ? `import bitranConfig from '${projectPath('bitran')}';` : ''}
|
|
26
|
+
export default ${config ? 'bitranConfig' : 'undefined'};
|
|
27
|
+
`,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const alias = (_nuxt.options.alias ||= {});
|
|
31
|
+
alias['#erudit/client/bitran'] = eruditEndNuxtPath(
|
|
32
|
+
`.nuxt/${templateFilename}`,
|
|
33
|
+
);
|
|
34
|
+
}
|
package/module/config.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { addTemplate } from 'nuxt/kit';
|
|
2
|
+
import type { Nuxt } from 'nuxt/schema';
|
|
3
|
+
import type { EruditConfig } from 'erudit-cog/schema';
|
|
4
|
+
|
|
5
|
+
import { eruditEndNuxtPath, projectPath } from '@erudit/globalPath';
|
|
6
|
+
import { logger } from '@erudit/module/logger';
|
|
7
|
+
|
|
8
|
+
export async function setupEruditConfig(_nuxt: Nuxt) {
|
|
9
|
+
let config: Partial<EruditConfig> = {};
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
const projectConfig = (await import(projectPath('erudit'))).default;
|
|
13
|
+
if (!projectConfig) throw new Error('Falsy Erudit config!');
|
|
14
|
+
config = projectConfig;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
logger.warn(`Failed to load Erudit config!\n\n${error}`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const templateFilename = '#erudit/config.ts';
|
|
20
|
+
|
|
21
|
+
addTemplate({
|
|
22
|
+
filename: templateFilename,
|
|
23
|
+
write: true,
|
|
24
|
+
getContents: () => `
|
|
25
|
+
import type { EruditConfig } from 'erudit-cog/schema';
|
|
26
|
+
export default ${JSON.stringify(config, null, ' ')} as Partial<EruditConfig>;
|
|
27
|
+
`,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const alias = (_nuxt.options.alias ||= {});
|
|
31
|
+
alias['#erudit/config'] = eruditEndNuxtPath(`.nuxt/${templateFilename}`);
|
|
32
|
+
|
|
33
|
+
return config;
|
|
34
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { addImports, addServerImports } from 'nuxt/kit';
|
|
2
|
+
|
|
3
|
+
import { eruditPath } from '@erudit/globalPath';
|
|
4
|
+
|
|
5
|
+
export function setupGlobalImports() {
|
|
6
|
+
addImports([
|
|
7
|
+
{
|
|
8
|
+
name: 'defineEruditConfig',
|
|
9
|
+
from: eruditPath('globals/erudit'),
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: 'defineContributor',
|
|
13
|
+
from: eruditPath('globals/contributor'),
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'defineBitranConfig',
|
|
17
|
+
from: eruditPath('globals/bitran'),
|
|
18
|
+
},
|
|
19
|
+
// Content
|
|
20
|
+
...(() => {
|
|
21
|
+
const imports = [
|
|
22
|
+
'defineBook',
|
|
23
|
+
'defineGroup',
|
|
24
|
+
'defineTopic',
|
|
25
|
+
'defineContentReferences',
|
|
26
|
+
];
|
|
27
|
+
return imports.map((name) => ({
|
|
28
|
+
name,
|
|
29
|
+
from: eruditPath(`globals/content`),
|
|
30
|
+
}));
|
|
31
|
+
})(),
|
|
32
|
+
// Helper Asset Path Functions
|
|
33
|
+
...(() => {
|
|
34
|
+
const imports = [
|
|
35
|
+
'eruditAsset',
|
|
36
|
+
'contributorAsset',
|
|
37
|
+
'contentAsset',
|
|
38
|
+
'publicAsset',
|
|
39
|
+
];
|
|
40
|
+
return imports.map((name) => ({
|
|
41
|
+
name,
|
|
42
|
+
from: eruditPath(`shared/asset`),
|
|
43
|
+
}));
|
|
44
|
+
})(),
|
|
45
|
+
]);
|
|
46
|
+
}
|
package/module/index.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { defineNuxtModule, updateTemplates } from 'nuxt/kit';
|
|
2
|
+
|
|
3
|
+
import { registerGlobals } from '@erudit/globals/register';
|
|
4
|
+
import { setupRestartWatcher } from '@erudit/module/restart';
|
|
5
|
+
import { setupEruditConfig } from '@erudit/module/config';
|
|
6
|
+
import { logger } from '@erudit/module/logger';
|
|
7
|
+
import { setupGlobalImports } from '@erudit/module/imports';
|
|
8
|
+
import { setupBitranConfig } from './bitran';
|
|
9
|
+
import { setupGlobalPaths } from './paths';
|
|
10
|
+
|
|
11
|
+
export default defineNuxtModule({
|
|
12
|
+
meta: { name: 'Erudit', configKey: 'erudit' },
|
|
13
|
+
async setup(_options, _nuxt) {
|
|
14
|
+
if (_nuxt.options.dev) setupRestartWatcher(_nuxt);
|
|
15
|
+
|
|
16
|
+
setupGlobalImports();
|
|
17
|
+
registerGlobals();
|
|
18
|
+
|
|
19
|
+
const eruditConfig = await setupEruditConfig(_nuxt);
|
|
20
|
+
await setupBitranConfig(_nuxt);
|
|
21
|
+
setupGlobalPaths(_nuxt);
|
|
22
|
+
|
|
23
|
+
if (eruditConfig.site?.baseUrl) {
|
|
24
|
+
const newBaseUrl = eruditConfig.site.baseUrl;
|
|
25
|
+
_nuxt.options.app.baseURL = newBaseUrl;
|
|
26
|
+
_nuxt.options.nitro.runtimeConfig!.app!.baseURL = newBaseUrl;
|
|
27
|
+
await updateTemplates();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// TODO: Watch for contributors folder and create/update template with their IDs
|
|
31
|
+
// TODO: Create such helpers for other features!
|
|
32
|
+
|
|
33
|
+
logger.success('Erudit module setup complete!');
|
|
34
|
+
},
|
|
35
|
+
});
|
package/module/logger.ts
ADDED
package/module/paths.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { addTemplate } from 'nuxt/kit';
|
|
2
|
+
import type { Nuxt } from 'nuxt/schema';
|
|
3
|
+
|
|
4
|
+
import { ERUDIT_DIR, eruditEndNuxtPath, PROJECT_DIR } from '@erudit/globalPath';
|
|
5
|
+
|
|
6
|
+
export function setupGlobalPaths(_nuxt: Nuxt) {
|
|
7
|
+
const templateFilename = '#erudit/globalPaths.ts';
|
|
8
|
+
|
|
9
|
+
addTemplate({
|
|
10
|
+
filename: templateFilename,
|
|
11
|
+
write: true,
|
|
12
|
+
getContents: () => `
|
|
13
|
+
export const ERUDIT_DIR = '${ERUDIT_DIR}';
|
|
14
|
+
export const PROJECT_DIR = '${PROJECT_DIR}';
|
|
15
|
+
`,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const alias = (_nuxt.options.alias ||= {});
|
|
19
|
+
alias['#erudit/globalPaths'] = eruditEndNuxtPath(
|
|
20
|
+
`.nuxt/${templateFilename}`,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { exit } from 'node:process';
|
|
2
|
+
import { globSync } from 'glob';
|
|
3
|
+
import chokidar, { type FSWatcher } from 'chokidar';
|
|
4
|
+
import type { Nuxt } from 'nuxt/schema';
|
|
5
|
+
|
|
6
|
+
import { eruditPath, projectPath } from '@erudit/globalPath';
|
|
7
|
+
import { logger } from '@erudit/module/logger';
|
|
8
|
+
import { stress } from '@erudit/utils/stress';
|
|
9
|
+
|
|
10
|
+
const watchTargets: string[] = [
|
|
11
|
+
// Erudit Nuxt config file
|
|
12
|
+
eruditPath('nuxt.config.ts'),
|
|
13
|
+
// Erudit Globals
|
|
14
|
+
eruditPath('globals'),
|
|
15
|
+
// Erudit Nuxt module non-runtime files
|
|
16
|
+
...globSync(eruditPath('module/**/*')),
|
|
17
|
+
// Erudit config in project root
|
|
18
|
+
...globSync(projectPath('erudit.{js,ts}')),
|
|
19
|
+
// Erudit Bitran config in project root
|
|
20
|
+
...globSync(projectPath('bitran.{js,ts}')),
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const ignoreTargets: string[] = [
|
|
24
|
+
// Erudit Nuxt module runtime files
|
|
25
|
+
...globSync(eruditPath('module/runtime/**/*')),
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const restartDelay = 300;
|
|
29
|
+
|
|
30
|
+
//
|
|
31
|
+
//
|
|
32
|
+
//
|
|
33
|
+
|
|
34
|
+
let watcher: FSWatcher;
|
|
35
|
+
let restartTimeout: any;
|
|
36
|
+
let nuxt: Nuxt;
|
|
37
|
+
|
|
38
|
+
export function setupRestartWatcher(_nuxt: Nuxt) {
|
|
39
|
+
nuxt = _nuxt;
|
|
40
|
+
|
|
41
|
+
if (watcher) return;
|
|
42
|
+
|
|
43
|
+
watcher = chokidar.watch(watchTargets, {
|
|
44
|
+
ignored: ignoreTargets,
|
|
45
|
+
ignoreInitial: true,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
watcher.on('all', (event, path) => {
|
|
49
|
+
clearTimeout(restartTimeout);
|
|
50
|
+
restartTimeout = setTimeout(() => {
|
|
51
|
+
console.log('\n');
|
|
52
|
+
logger.info(
|
|
53
|
+
`Restarting due to critical file change: ${stress(path)}\n\n`,
|
|
54
|
+
);
|
|
55
|
+
// Nuxt Restart Hook won't work when unhandled Node exception is thrown!
|
|
56
|
+
// nuxt.callHook('restart', { hard: true, });
|
|
57
|
+
// So we kill the process and restart it in Erudit CLI instead.
|
|
58
|
+
exit(1337);
|
|
59
|
+
}, restartDelay);
|
|
60
|
+
});
|
|
61
|
+
}
|
package/nuxt.config.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { eruditPath, projectPath } from './globalPath';
|
|
2
|
+
|
|
3
|
+
export default defineNuxtConfig({
|
|
4
|
+
compatibilityDate: '2025-01-01',
|
|
5
|
+
devtools: { enabled: true },
|
|
6
|
+
future: { compatibilityVersion: 4 },
|
|
7
|
+
ssr: true,
|
|
8
|
+
alias: {
|
|
9
|
+
'@erudit': eruditPath(),
|
|
10
|
+
'@module': eruditPath('module'),
|
|
11
|
+
'@server': eruditPath('server/plugin'),
|
|
12
|
+
'@shared': eruditPath('shared'),
|
|
13
|
+
'@app': eruditPath('app'),
|
|
14
|
+
$: eruditPath('app/styles'),
|
|
15
|
+
},
|
|
16
|
+
modules: [eruditPath('module'), 'nuxt-my-icons'],
|
|
17
|
+
myicons: {
|
|
18
|
+
iconsDir: eruditPath('app/assets/icons'),
|
|
19
|
+
},
|
|
20
|
+
typescript: {
|
|
21
|
+
tsConfig: {
|
|
22
|
+
include: [eruditPath('**/*'), projectPath('**/*')],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
ignore: [
|
|
26
|
+
// Content assets
|
|
27
|
+
...[
|
|
28
|
+
'**/{book,group,topic}.{js,ts}',
|
|
29
|
+
'**/{article,summary,practice,content}.bi',
|
|
30
|
+
].map((pattern) => projectPath(`content/${pattern}`)),
|
|
31
|
+
// Contributors assets
|
|
32
|
+
...['*/contributor.{js,ts}', '*/description.bi'].map((pattern) =>
|
|
33
|
+
projectPath(`contributors/${pattern}`),
|
|
34
|
+
),
|
|
35
|
+
],
|
|
36
|
+
nitro: {
|
|
37
|
+
plugins: [eruditPath('server/plugin')],
|
|
38
|
+
prerender: {
|
|
39
|
+
failOnError: false,
|
|
40
|
+
},
|
|
41
|
+
output: {
|
|
42
|
+
publicDir: projectPath('dist'),
|
|
43
|
+
},
|
|
44
|
+
publicAssets: [
|
|
45
|
+
{
|
|
46
|
+
baseURL: '/_erudit-asset/',
|
|
47
|
+
dir: eruditPath('app/public'),
|
|
48
|
+
maxAge: 60 * 60 * 24 * 30,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
baseURL: '/_user-asset/public/',
|
|
52
|
+
dir: projectPath('public'),
|
|
53
|
+
maxAge: 60 * 60 * 24 * 30,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
baseURL: '/_user-asset/content/',
|
|
57
|
+
dir: projectPath('content'),
|
|
58
|
+
maxAge: 60 * 60 * 24 * 30,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
baseURL: '/_user-asset/contributor/',
|
|
62
|
+
dir: projectPath('contributors'),
|
|
63
|
+
maxAge: 60 * 60 * 24 * 30,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
esbuild: {
|
|
67
|
+
options: {
|
|
68
|
+
tsconfigRaw: {
|
|
69
|
+
compilerOptions: {
|
|
70
|
+
experimentalDecorators: true, // Make TypeORM work with Nuxt
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
vite: {
|
|
77
|
+
optimizeDeps: {
|
|
78
|
+
include: [
|
|
79
|
+
'@floating-ui/vue',
|
|
80
|
+
'bitran',
|
|
81
|
+
'bitran/core',
|
|
82
|
+
'bitran/render',
|
|
83
|
+
'yaml',
|
|
84
|
+
'slugify',
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
css: {
|
|
88
|
+
preprocessorOptions: {
|
|
89
|
+
scss: {
|
|
90
|
+
api: 'modern-compiler',
|
|
91
|
+
additionalData: `@use '$/utils' as *;`,
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "erudit",
|
|
3
|
+
"version": "2.0.0-dev.7",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "🤓 CMS for perfect educational sites.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "./nuxt.config.ts",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/erudit-js/erudit.git",
|
|
11
|
+
"directory": "packages/erudit"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@floating-ui/vue": "^1.1.6",
|
|
15
|
+
"bitran": "^3.0.0-dev.3",
|
|
16
|
+
"chalk": "^5.4.1",
|
|
17
|
+
"chokidar": "^4.0.3",
|
|
18
|
+
"consola": "^3.4.0",
|
|
19
|
+
"erudit-cli": "1.0.0-dev.6",
|
|
20
|
+
"erudit-cog": "1.0.0-dev.3",
|
|
21
|
+
"glob": "^11.0.1",
|
|
22
|
+
"image-size": "^1.2.0",
|
|
23
|
+
"nuxt": "3.15.4",
|
|
24
|
+
"nuxt-my-icons": "1.0.2",
|
|
25
|
+
"sass": "^1.84.0",
|
|
26
|
+
"slugify": "^1.6.6",
|
|
27
|
+
"sqlite3": "^5.1.7",
|
|
28
|
+
"typeorm": "^0.3.20",
|
|
29
|
+
"vue": "latest",
|
|
30
|
+
"vue-router": "latest"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ERUDIT_SERVER } from '@server/global';
|
|
2
|
+
import { createBookFrontNav } from '@server/repository/frontNav';
|
|
3
|
+
|
|
4
|
+
export default defineEventHandler(async (event) => {
|
|
5
|
+
const bookId = getRouterParam(event, 'bookId');
|
|
6
|
+
|
|
7
|
+
if (
|
|
8
|
+
!bookId ||
|
|
9
|
+
!ERUDIT_SERVER.NAV_BOOKS ||
|
|
10
|
+
!(bookId in ERUDIT_SERVER.NAV_BOOKS)
|
|
11
|
+
)
|
|
12
|
+
throw createError({
|
|
13
|
+
statusCode: 400,
|
|
14
|
+
statusText: `Unknown book id "${bookId}"!`,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const bookNode = ERUDIT_SERVER.NAV_BOOKS[bookId]!;
|
|
18
|
+
|
|
19
|
+
return await createBookFrontNav(bookNode);
|
|
20
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FrontNav } from '@erudit/shared/frontNav';
|
|
2
|
+
import { ERUDIT_SERVER } from '@server/global';
|
|
3
|
+
import { createGlobalFrontNav } from '@server/repository/frontNav';
|
|
4
|
+
|
|
5
|
+
export default defineEventHandler(async () => {
|
|
6
|
+
return (await createGlobalFrontNav(ERUDIT_SERVER.NAV, false)) as FrontNav;
|
|
7
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { getTopicPartsLinks } from '@server/repository/topic';
|
|
2
|
+
import { getContentBookFor } from '@server/repository/book';
|
|
3
|
+
import { getContentGenericData } from '@server/repository/content';
|
|
4
|
+
|
|
5
|
+
import type { ContentGenericData } from '@shared/content/data/base';
|
|
6
|
+
import type { ContentTopicData } from '@shared/content/data/type/topic';
|
|
7
|
+
import type { ContentGroupData } from '@shared/content/data/type/group';
|
|
8
|
+
import type { ContentBookData } from '@shared/content/data/type/book';
|
|
9
|
+
|
|
10
|
+
export default defineEventHandler(async (event) => {
|
|
11
|
+
const contentId = getQuery(event)?.contentId as string;
|
|
12
|
+
|
|
13
|
+
if (!contentId)
|
|
14
|
+
throw createError({
|
|
15
|
+
statusCode: 400,
|
|
16
|
+
statusText: 'Missing content ID!',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const generic = await getContentGenericData(contentId);
|
|
20
|
+
|
|
21
|
+
switch (generic.type) {
|
|
22
|
+
case 'topic':
|
|
23
|
+
return await getTopicData(generic);
|
|
24
|
+
case 'group':
|
|
25
|
+
return await getGroupData(generic);
|
|
26
|
+
case 'book':
|
|
27
|
+
return await getBookData(generic);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
throw createError({
|
|
31
|
+
statusCode: 400,
|
|
32
|
+
statusText: `Unknown content data type "${generic.type}"!`,
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
//
|
|
37
|
+
//
|
|
38
|
+
//
|
|
39
|
+
|
|
40
|
+
async function getTopicData(
|
|
41
|
+
generic: ContentGenericData,
|
|
42
|
+
): Promise<ContentTopicData> {
|
|
43
|
+
const contentBook = await getContentBookFor(generic.contentId);
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
type: 'topic',
|
|
47
|
+
generic,
|
|
48
|
+
bookTitle: contentBook?.title,
|
|
49
|
+
topicPartLinks: await getTopicPartsLinks(generic.contentId),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function getGroupData(
|
|
54
|
+
generic: ContentGenericData,
|
|
55
|
+
): Promise<ContentGroupData> {
|
|
56
|
+
const contentBook = await getContentBookFor(generic.contentId);
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
type: 'group',
|
|
60
|
+
generic,
|
|
61
|
+
bookTitle: contentBook?.title,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function getBookData(
|
|
66
|
+
generic: ContentGenericData,
|
|
67
|
+
): Promise<ContentBookData> {
|
|
68
|
+
return {
|
|
69
|
+
type: 'book',
|
|
70
|
+
generic,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ERUDIT_SERVER } from '@server/global';
|
|
2
|
+
|
|
3
|
+
export default defineEventHandler(() => {
|
|
4
|
+
const strFunctions: Record<string, string> = {};
|
|
5
|
+
|
|
6
|
+
for (const [key, func] of Object.entries(
|
|
7
|
+
ERUDIT_SERVER.LANGUAGE?.functions || {},
|
|
8
|
+
))
|
|
9
|
+
strFunctions[key] = 'return ' + func.toString();
|
|
10
|
+
|
|
11
|
+
return strFunctions;
|
|
12
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { EruditPhraseId } from '@shared/types/language';
|
|
2
|
+
import { ERUDIT_SERVER } from '@server/global';
|
|
3
|
+
|
|
4
|
+
export default defineEventHandler((event) => {
|
|
5
|
+
const phraseId = getRouterParam(event, 'phraseId');
|
|
6
|
+
const phrase =
|
|
7
|
+
ERUDIT_SERVER.LANGUAGE?.phrases?.[phraseId as EruditPhraseId];
|
|
8
|
+
|
|
9
|
+
setResponseHeader(event, 'content-type', 'text/plain');
|
|
10
|
+
|
|
11
|
+
if (typeof phrase === 'string') return phrase;
|
|
12
|
+
else if (typeof phrase === 'function')
|
|
13
|
+
return '~!~FUNC~!~' + 'return ' + phrase.toString();
|
|
14
|
+
|
|
15
|
+
throw createError({
|
|
16
|
+
statusCode: 400,
|
|
17
|
+
statusText: `Unknown phrase id "${phraseId}"!`,
|
|
18
|
+
});
|
|
19
|
+
});
|