Skip to content

Commit

Permalink
Add new repository hosting API (#56)
Browse files Browse the repository at this point in the history
* Add new repository hosting API

* Create five-needles-stare.md
  • Loading branch information
yanthomasdev authored Nov 27, 2023
1 parent 1ca476a commit 92bee73
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 141 deletions.
5 changes: 5 additions & 0 deletions .changeset/five-needles-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@lunariajs/core": patch
---

Add new repository hosting API
6 changes: 4 additions & 2 deletions examples/vitepress/lunaria.config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"repository": "https://github.com/Yan-Thomas/lunaria",
"rootDir": "./examples/vitepress",
"repository": {
"name": "Yan-Thomas/lunaria",
"rootDir": "examples/vitepress"
},
"dashboard": {
"url": "https://localhost:3000/"
},
Expand Down
82 changes: 56 additions & 26 deletions packages/core/src/dashboard/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,15 @@ export const LocaleDetails = (
${missingPages.map(
(page) => html`
<li>
${Link(page.gitHubURL, page.sharedPath)}
${CreatePageLink(
page.translations[lang]?.gitHubURL!,
dashboard.ui['statusByLocale.createFileLink']
)}
${page.gitHostingFileURL
? Link(page.gitHostingFileURL, page.sharedPath)
: page.sharedPath}
${page.translations[lang]?.gitHostingFileURL
? CreatePageLink(
page.translations[lang]?.gitHostingFileURL!,
dashboard.ui['statusByLocale.createFileLink']
)
: ''}
</li>
`
)}
Expand Down Expand Up @@ -219,7 +223,7 @@ export const TableBody = (
(page) =>
html`
<tr>
<td>${Link(page.gitHubURL, page.sharedPath)}</td>
<td>${page.gitHostingFileURL ? Link(page.gitHostingFileURL, page.sharedPath) : page.sharedPath}</td>
${locales.map(({ lang }) => {
return TableContentStatus(page.translations, lang, dashboard);
})}
Expand All @@ -238,16 +242,10 @@ export const TableContentStatus = (
return html`
<td>
${translations[lang]?.isMissing
? html`<span title="${dashboard.ui['status.missing']}"
><span aria-hidden="true">${dashboard.ui['status.emojiMissing']}</span></span
>`
? EmojiFileLink(dashboard.ui, translations[lang]?.gitHostingFileURL!, 'missing')
: translations[lang]?.isOutdated || !translations[lang]?.completeness.complete
? html`<a href="${translations[lang]?.gitHubURL}" title="${dashboard.ui['status.outdated']}"
><span aria-hidden="true">${dashboard.ui['status.emojiOutdated']}</span></a
>`
: html`<a href="${translations[lang]?.gitHubURL}" title="${dashboard.ui['status.done']}"
><span aria-hidden="true">${dashboard.ui['status.emojiDone']}</span></a
>`}
? EmojiFileLink(dashboard.ui, translations[lang]?.gitHostingFileURL!, 'outdated')
: EmojiFileLink(dashboard.ui, translations[lang]?.gitHostingFileURL!, 'done')}
</td>
`;
};
Expand All @@ -258,22 +256,54 @@ export const ContentDetailsLinks = (
dashboard: Dashboard
) => {
return html`
${Link(page.gitHubURL, page.sharedPath)}
${page.gitHostingFileURL ? Link(page.gitHostingFileURL, page.sharedPath) : page.sharedPath}
${page.translations[lang]
? html`(${Link(
page.translations[lang]?.gitHubURL!,
!page.translations[lang]?.completeness.complete
? dashboard.ui['statusByLocale.incompleteTranslationLink']
: dashboard.ui['statusByLocale.outdatedTranslationLink']
)},
${Link(
page.translations[lang]?.sourceHistoryURL!,
dashboard.ui['statusByLocale.sourceChangeHistoryLink']
)})`
? page.translations[lang]?.gitHostingFileURL || page.translations[lang]?.gitHostingHistoryURL
? html`(${page.translations[lang]?.gitHostingFileURL
? Link(
page.translations[lang]?.gitHostingFileURL!,
!page.translations[lang]?.completeness.complete
? dashboard.ui['statusByLocale.incompleteTranslationLink']
: dashboard.ui['statusByLocale.outdatedTranslationLink']
)
: ''},
${page.translations[lang]?.gitHostingHistoryURL
? Link(
page.translations[lang]?.gitHostingHistoryURL!,
dashboard.ui['statusByLocale.sourceChangeHistoryLink']
)
: ''})`
: ''
: ''}
`;
};

export const EmojiFileLink = (
ui: Dashboard['ui'],
href: string | null,
status: 'missing' | 'outdated' | 'done'
) => {
const statusTextOpts = {
missing: 'status.missing',
outdated: 'status.outdated',
done: 'status.done',
} as const;

const statusEmojiOpts = {
missing: 'status.emojiMissing',
outdated: 'status.emojiOutdated',
done: 'status.emojiDone',
} as const;

return href
? html`<a href="${href}" title="${ui[statusTextOpts[status]]}">
<span aria-hidden="true">${ui[statusEmojiOpts[status]]}</span>
</a>`
: html`<span title="${ui[statusTextOpts[status]]}">
<span aria-hidden="true">${ui[statusEmojiOpts[status]]}</span>
</span>`;
};

export const Link = (href: string, text: string) => {
return html`<a href="${href}">${text}</a>`;
};
Expand Down
84 changes: 46 additions & 38 deletions packages/core/src/schemas/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { normalizeURL } from 'ufo';
import { isRelative, withoutTrailingSlash } from 'ufo';
import { z } from 'zod';
import { DashboardSchema } from '../schemas/dashboard.js';
import { LocaleSchema } from '../schemas/locale.js';
Expand All @@ -14,24 +14,67 @@ function createComponentSchema<ComponentType extends CustomComponent | CustomSta
}

export const customRoutingStrategyOptionsSchema = z.object({
/** The regex pattern to find the path section to be replaced. You can use :locales to dynamically add a list of all the locales in the format `'es|pt|ar'`. */
regex: z
.string()
.describe(
"A regex pattern to find the path section to be replaced. You can use :lunaria-locales to dynamically add a list of all the locales in the format `'es|pt|ar'`."
"The regex pattern to find the path section to be replaced. You can use :locales to dynamically add a list of all the locales in the format `'es|pt|ar'`."
),
/** The content that will be replaced into the `toLocalePath` regex's match. You can use :locale to dynamically add the current locale for you to replace with. */
localePathReplaceWith: z
.string()
.describe(
"The content that will be replaced into the `toLocalePath` regex's match. You can use :lunaria-locale to dynamically add the current locale for you to replace with."
"The content that will be replaced into the `toLocalePath` regex's match. You can use :locale to dynamically add the current locale for you to replace with."
),
/** The content that will be replaced into the `toSharedPath` regex's match. */
sharedPathReplaceWith: z
.string()
.describe("The content that will be replaced into the `toSharedPath` regex's match."),
});

export const customGitHostingOptionsSchema = z.object({
create: z.string().or(z.null()),
source: z.string().or(z.null()),
history: z.string().or(z.null()),
clone: z.string(),
});

export const repositorySchema = z.object({
/** The unique name of your repository in your git hosting platform, e.g. `"Yan-Thomas/lunaria"`. */
name: z
.string()
.transform((path) => withoutTrailingSlash(path))
.describe(
'The unique name of your repository in your git hosting platform, e.g. `"Yan-Thomas/lunaria"`.'
),
/** The currently tracked branch of your repository. */
branch: z.string().default('main').describe('The currently tracked branch of your repository.'),
/** The root directory of the project being tracked, must be set when using a monorepo. */
rootDir: z
.string()
.default('')
.refine((path) => !isRelative(path) || path === '', {
message:
'The root directory should not be a relative path, it should follow the example: `examples/vitepress`.',
})
.transform((path) => withoutTrailingSlash(path))
.describe(
'The root directory of the project being tracked, must be set when using a monorepo.'
),
/** The git hosting platform used by your project, e.g. `"github"` or `"gitlab"`. */
hosting: z
.literal('github')
.or(z.literal('gitlab'))
.or(customGitHostingOptionsSchema)
.default('github')
.describe('The git hosting platform used by your project, e.g. `"github"` or `"gitlab"`.'),
});

export const LunariaConfigSchema = z.object({
/** Options about your generated dashboard. */
dashboard: DashboardSchema,
/** Information about your project's repository. */
repository: repositorySchema,
/** The default locale of your content that is going to be translated. */
defaultLocale: LocaleSchema,
/** Array of the locales that will be translated. */
Expand All @@ -58,41 +101,6 @@ export const LunariaConfigSchema = z.object({
.describe(
"The routing strategy used by your framework, used to properly generate paths from a locale's path."
),
/** The URL of your current repository, used to generate history links, e.g. `"https://github.com/Yan-Thomas/lunaria/"`. */
repository: z
.string()
.url()
.refine((url) => url.startsWith('https://github.com/'), {
message: 'URL needs to be a valid GitHub link (`"https://github.com/"`).',
})
.transform((url) => normalizeURL(url))
.describe(
'The URL of your current repository, used to generate history links, e.g. `"https://github.com/Yan-Thomas/lunaria/"`.'
),
/** The root directory of the project being tracked, must be set when using a monorepo.
*
* @example
* Take this project structure as an example:
* ```md
* ├── docs/
* ├── packages/
* | ├── package-one/
* | ├── package-two/
* ```
* Considering you're tracking your docs located at `docs/`, `rootDir` should be defined like the following:
* ```json
* rootDir: "./docs"
* ```
*
* This is necessary because when using a shallow repository, as the entire monorepo is downloaded,
* and therefore there's no other way to reliably know where your content being tracked is.
*/
rootDir: z
.string()
.default('.')
.describe(
'The root directory of the project being tracked, must be set when using a monorepo.'
),
/** The relative directory path of where your dashboard will build to, e.g. `"./dist/translation-status/index.html"`. */
outDir: z
.string()
Expand Down
Loading

0 comments on commit 92bee73

Please sign in to comment.