mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-25 10:33:21 +03:00
Merge branch 'master' into feat/parse-binary-file
This commit is contained in:
commit
59513b8d99
@ -33,6 +33,7 @@
|
||||
"@codemirror/language": "^6.10.2",
|
||||
"@codemirror/legacy-modes": "^6.4.0",
|
||||
"@gitbutler/ui": "workspace:*",
|
||||
"@gitbutler/shared": "workspace:*",
|
||||
"@lezer/common": "^1.2.1",
|
||||
"@lezer/highlight": "^1.2.0",
|
||||
"@octokit/rest": "^20.1.1",
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { splitPromptMessages } from './anthropicUtils';
|
||||
import {
|
||||
SHORT_DEFAULT_COMMIT_TEMPLATE,
|
||||
SHORT_DEFAULT_BRANCH_TEMPLATE,
|
||||
@ -11,29 +12,11 @@ import {
|
||||
} from '$lib/ai/types';
|
||||
import { andThenAsync, ok, wrapAsync, type Result } from '$lib/result';
|
||||
import Anthropic from '@anthropic-ai/sdk';
|
||||
import type { MessageParam, RawMessageStreamEvent } from '@anthropic-ai/sdk/resources/messages.mjs';
|
||||
import type { RawMessageStreamEvent } from '@anthropic-ai/sdk/resources/messages.mjs';
|
||||
import type { Stream } from '@anthropic-ai/sdk/streaming.mjs';
|
||||
|
||||
const DEFAULT_MAX_TOKENS = 1024;
|
||||
|
||||
function splitPromptMessages(prompt: Prompt): [MessageParam[], string | undefined] {
|
||||
const messages: MessageParam[] = [];
|
||||
let system: string | undefined = undefined;
|
||||
for (const message of prompt) {
|
||||
if (message.role === 'system') {
|
||||
system = message.content;
|
||||
continue;
|
||||
}
|
||||
|
||||
messages.push({
|
||||
role: message.role,
|
||||
content: message.content
|
||||
});
|
||||
}
|
||||
|
||||
return [messages, system];
|
||||
}
|
||||
|
||||
export class AnthropicAIClient implements AIClient {
|
||||
defaultCommitTemplate = SHORT_DEFAULT_COMMIT_TEMPLATE;
|
||||
defaultBranchTemplate = SHORT_DEFAULT_BRANCH_TEMPLATE;
|
||||
|
35
apps/desktop/src/lib/ai/anthropicUtils.ts
Normal file
35
apps/desktop/src/lib/ai/anthropicUtils.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { isMessageRole, type Prompt } from './types';
|
||||
import { isStr } from '$lib/utils/string';
|
||||
import type { MessageParam } from '@anthropic-ai/sdk/resources/messages.mjs';
|
||||
|
||||
export function splitPromptMessages(prompt: Prompt): [MessageParam[], string | undefined] {
|
||||
const messages: MessageParam[] = [];
|
||||
let system: string | undefined = undefined;
|
||||
for (const message of prompt) {
|
||||
if (message.role === 'system') {
|
||||
system = message.content;
|
||||
continue;
|
||||
}
|
||||
|
||||
messages.push({
|
||||
role: message.role,
|
||||
content: message.content
|
||||
});
|
||||
}
|
||||
|
||||
return [messages, system];
|
||||
}
|
||||
|
||||
export function messageParamToPrompt(messages: MessageParam[]): Prompt {
|
||||
const result: Prompt = [];
|
||||
for (const message of messages) {
|
||||
if (!isStr(message.content)) continue;
|
||||
if (!isMessageRole(message.role)) continue;
|
||||
|
||||
result.push({
|
||||
role: message.role,
|
||||
content: message.content
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
@ -1,12 +1,28 @@
|
||||
import { messageParamToPrompt, splitPromptMessages } from './anthropicUtils';
|
||||
import {
|
||||
SHORT_DEFAULT_BRANCH_TEMPLATE,
|
||||
SHORT_DEFAULT_COMMIT_TEMPLATE,
|
||||
SHORT_DEFAULT_PR_TEMPLATE
|
||||
} from '$lib/ai/prompts';
|
||||
import { ModelKind, type AIClient, type Prompt } from '$lib/ai/types';
|
||||
import { map, type Result } from '$lib/result';
|
||||
import type { AIClient, ModelKind, Prompt } from '$lib/ai/types';
|
||||
import type { HttpClient } from '$lib/backend/httpClient';
|
||||
|
||||
function splitPromptMessagesIfNecessary(
|
||||
modelKind: ModelKind,
|
||||
prompt: Prompt
|
||||
): [Prompt, string | undefined] {
|
||||
switch (modelKind) {
|
||||
case ModelKind.Anthropic: {
|
||||
const [messages, system] = splitPromptMessages(prompt);
|
||||
return [messageParamToPrompt(messages), system];
|
||||
}
|
||||
case ModelKind.OpenAI:
|
||||
case ModelKind.Ollama:
|
||||
return [prompt, undefined];
|
||||
}
|
||||
}
|
||||
|
||||
export class ButlerAIClient implements AIClient {
|
||||
defaultCommitTemplate = SHORT_DEFAULT_COMMIT_TEMPLATE;
|
||||
defaultBranchTemplate = SHORT_DEFAULT_BRANCH_TEMPLATE;
|
||||
@ -19,11 +35,13 @@ export class ButlerAIClient implements AIClient {
|
||||
) {}
|
||||
|
||||
async evaluate(prompt: Prompt): Promise<Result<string, Error>> {
|
||||
const [messages, system] = splitPromptMessagesIfNecessary(this.modelKind, prompt);
|
||||
const response = await this.cloud.postSafe<{ message: string }>(
|
||||
'evaluate_prompt/predict.json',
|
||||
{
|
||||
body: {
|
||||
messages: prompt,
|
||||
messages,
|
||||
system,
|
||||
max_tokens: 400,
|
||||
model_kind: this.modelKind
|
||||
},
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { isStr } from '$lib/utils/string';
|
||||
import type { Persisted } from '$lib/persisted/persisted';
|
||||
import type { Result } from '$lib/result';
|
||||
|
||||
@ -30,6 +31,12 @@ export enum MessageRole {
|
||||
Assistant = 'assistant'
|
||||
}
|
||||
|
||||
export function isMessageRole(role: unknown): role is MessageRole {
|
||||
if (!isStr(role)) return false;
|
||||
const roles = Object.values(MessageRole);
|
||||
return roles.includes(role as MessageRole);
|
||||
}
|
||||
|
||||
export interface PromptMessage {
|
||||
content: string;
|
||||
role: MessageRole;
|
||||
|
@ -47,10 +47,10 @@
|
||||
if (topPatch.remoteCommitId !== topPatch.id) return true;
|
||||
return false;
|
||||
});
|
||||
const branchColorType = $derived<CommitStatus | 'localAndShadow'>(
|
||||
const branchType = $derived<CommitStatus | 'localAndShadow'>(
|
||||
hasShadow ? 'localAndShadow' : topPatch?.status ?? 'local'
|
||||
);
|
||||
const lineColor = $derived(getColorFromBranchType(branchColorType));
|
||||
const lineColor = $derived(getColorFromBranchType(branchType));
|
||||
|
||||
// Pretty cumbersome way of getting the PR number, would be great if we can
|
||||
// make it more concise somehow.
|
||||
@ -69,7 +69,9 @@
|
||||
}
|
||||
|
||||
function editTitle(title: string) {
|
||||
branchController.updateBranchName(branch.id, title);
|
||||
if (currentSeries?.name && title !== currentSeries.name) {
|
||||
branchController.updateSeriesName(branch.id, currentSeries.name, title);
|
||||
}
|
||||
}
|
||||
|
||||
function editDescription(_description: string) {
|
||||
@ -83,21 +85,29 @@
|
||||
|
||||
<div class="branch-header">
|
||||
<div class="branch-info">
|
||||
<StackingStatusIcon icon="tick-small" iconColor="#fff" color={lineColor} gap={false} lineTop />
|
||||
<StackingStatusIcon
|
||||
icon={branchType === 'integrated' ? 'tick-small' : 'remote-branch-small'}
|
||||
iconColor="#fff"
|
||||
color={lineColor}
|
||||
gap={false}
|
||||
lineTop
|
||||
/>
|
||||
<div class="text-14 text-bold branch-info__name">
|
||||
<span class="remote-name">{$baseBranch.remoteName ?? 'origin'}/</span>
|
||||
<BranchLabel {name} onChange={(name) => editTitle(name)} />
|
||||
<Button
|
||||
size="tag"
|
||||
icon="open-link"
|
||||
style="ghost"
|
||||
onclick={(e: MouseEvent) => {
|
||||
const url = gitHostBranch?.url;
|
||||
if (url) openExternalUrl(url);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
></Button>
|
||||
{#if gitHostBranch}
|
||||
<Button
|
||||
size="tag"
|
||||
icon="open-link"
|
||||
style="ghost"
|
||||
onclick={(e: MouseEvent) => {
|
||||
const url = gitHostBranch?.url;
|
||||
if (url) openExternalUrl(url);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
></Button>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="branch-info__btns">
|
||||
<Button
|
||||
@ -127,33 +137,43 @@
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="branch-action">
|
||||
<div class="branch-action__line" style:--bg-color={lineColor}></div>
|
||||
<div class="branch-action__body">
|
||||
{#if $pr}
|
||||
<StackingPullRequestCard pr={$pr} {prMonitor} sourceBranch={$pr.sourceBranch} />
|
||||
{:else}
|
||||
<Button
|
||||
style="ghost"
|
||||
wide
|
||||
outline
|
||||
disabled={commits.length === 0 || !$gitHost || !$prService}
|
||||
onclick={handleOpenPR}>Create pull request</Button
|
||||
>
|
||||
{/if}
|
||||
{#if gitHostBranch}
|
||||
<div class="branch-action">
|
||||
<div class="branch-action__line" style:--bg-color={lineColor}></div>
|
||||
<div class="branch-action__body">
|
||||
{#if $pr}
|
||||
<StackingPullRequestCard pr={$pr} {prMonitor} sourceBranch={$pr.sourceBranch} />
|
||||
{:else}
|
||||
<Button
|
||||
style="ghost"
|
||||
wide
|
||||
outline
|
||||
disabled={commits.length === 0 || !$gitHost || !$prService}
|
||||
onclick={handleOpenPR}>Create pull request</Button
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<PrDetailsModal
|
||||
bind:this={prDetailsModal}
|
||||
type="preview-series"
|
||||
{upstreamName}
|
||||
{name}
|
||||
{commits}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<PrDetailsModal bind:this={prDetailsModal} type="preview-series" {upstreamName} {name} {commits} />
|
||||
|
||||
<style lang="postcss">
|
||||
.branch-header {
|
||||
display: flex;
|
||||
border-bottom: 1px solid var(--clr-border-2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px solid var(--clr-border-2);
|
||||
}
|
||||
}
|
||||
|
||||
.branch-info {
|
||||
|
@ -4,7 +4,7 @@
|
||||
const FALLBACK_COLOR = 'var(--clr-scale-ntrl-80)';
|
||||
|
||||
interface Props {
|
||||
icon: 'plus-small' | 'tick-small' | 'virtual-branch-small';
|
||||
icon: 'plus-small' | 'tick-small' | 'remote-branch-small';
|
||||
iconColor?: string;
|
||||
color?: string;
|
||||
gap?: boolean;
|
||||
|
@ -55,6 +55,9 @@
|
||||
let files: RemoteFile[] = [];
|
||||
let showDetails = false;
|
||||
|
||||
$: conflicted = commit.conflicted;
|
||||
$: isAncestorMostConflicted = branch?.ancestorMostConflictedCommit?.id === commit.id;
|
||||
|
||||
async function loadFiles() {
|
||||
files = await listRemoteCommitFiles(project.id, commit.id);
|
||||
}
|
||||
@ -91,6 +94,8 @@
|
||||
let createRefModal: Modal;
|
||||
let createRefName = $baseBranch.remoteName + '/';
|
||||
|
||||
let conflictResolutionConfirmationModal: ReturnType<typeof Modal> | undefined;
|
||||
|
||||
function openCommitMessageModal(e: Event) {
|
||||
e.stopPropagation();
|
||||
|
||||
@ -138,11 +143,16 @@
|
||||
|
||||
async function editPatch() {
|
||||
if (!canEdit()) return;
|
||||
|
||||
modeService!.enterEditMode(commit.id, branch!.refname);
|
||||
}
|
||||
|
||||
$: conflicted = commit.conflicted;
|
||||
async function handleEditPatch() {
|
||||
if (conflicted && !isAncestorMostConflicted) {
|
||||
conflictResolutionConfirmationModal?.show();
|
||||
return;
|
||||
}
|
||||
await editPatch();
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal bind:this={commitMessageModal} width="small" onSubmit={submitCommitMessageModal}>
|
||||
@ -187,6 +197,20 @@
|
||||
{/snippet}
|
||||
</Modal>
|
||||
|
||||
<Modal bind:this={conflictResolutionConfirmationModal} width="small" onSubmit={editPatch}>
|
||||
{#snippet children()}
|
||||
<div>
|
||||
<p>It's generally better to start resolving conflicts from the bottom up.</p>
|
||||
<br />
|
||||
<p>Are you sure you want to resolve conflicts for this commit?</p>
|
||||
</div>
|
||||
{/snippet}
|
||||
{#snippet controls(close)}
|
||||
<Button style="ghost" outline type="reset" onclick={close}>Cancel</Button>
|
||||
<Button style="pop" outline type="submit">Yes</Button>
|
||||
{/snippet}
|
||||
</Modal>
|
||||
|
||||
<CommitContextMenu
|
||||
bind:this={contextMenu}
|
||||
targetElement={draggableCommitElement}
|
||||
@ -397,7 +421,7 @@
|
||||
>
|
||||
{/if}
|
||||
{#if canEdit()}
|
||||
<Button size="tag" style="ghost" outline onclick={editPatch}>
|
||||
<Button size="tag" style="ghost" outline onclick={handleEditPatch}>
|
||||
{#if conflicted}
|
||||
Resolve conflicts
|
||||
{:else}
|
||||
|
@ -52,8 +52,8 @@
|
||||
let aiLoading = false;
|
||||
let aiConfigurationValid = false;
|
||||
|
||||
let titleTextArea: HTMLTextAreaElement;
|
||||
let descriptionTextArea: HTMLTextAreaElement;
|
||||
let titleTextArea: HTMLTextAreaElement | undefined;
|
||||
let descriptionTextArea: HTMLTextAreaElement | undefined;
|
||||
|
||||
$: ({ title, description } = splitMessage(commitMessage));
|
||||
$: valid = !!title;
|
||||
@ -138,7 +138,7 @@
|
||||
if (e.key === KeyName.Delete && value.length === 0) {
|
||||
e.preventDefault();
|
||||
if (titleTextArea) {
|
||||
titleTextArea?.focus();
|
||||
titleTextArea.focus();
|
||||
titleTextArea.selectionStart = titleTextArea.textLength;
|
||||
}
|
||||
autoHeight(e.currentTarget);
|
||||
@ -178,9 +178,11 @@
|
||||
: `${toMove}\n${description}`;
|
||||
commitMessage = concatMessage(toKeep, newDescription);
|
||||
tick().then(() => {
|
||||
descriptionTextArea?.focus();
|
||||
descriptionTextArea.setSelectionRange(0, 0);
|
||||
autoHeight(descriptionTextArea);
|
||||
if (descriptionTextArea) {
|
||||
descriptionTextArea.focus();
|
||||
descriptionTextArea.setSelectionRange(0, 0);
|
||||
autoHeight(descriptionTextArea);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -402,6 +402,10 @@
|
||||
&:not(.is-last) {
|
||||
border-bottom: 1px solid var(--clr-border-2);
|
||||
}
|
||||
|
||||
&.is-last {
|
||||
border-radius: 0 0 var(--radius-m) var(--radius-m);
|
||||
}
|
||||
}
|
||||
|
||||
.commit-card {
|
||||
|
@ -34,7 +34,7 @@
|
||||
<StackingBranchHeader
|
||||
commits={currentSeries.patches}
|
||||
name={currentSeries.branchName}
|
||||
upstreamName={currentSeries.name}
|
||||
upstreamName={currentSeries.upstreamReference ? currentSeries.name : undefined}
|
||||
/>
|
||||
<StackingCommitList
|
||||
remoteOnlyPatches={currentSeries.upstreamPatches}
|
||||
|
@ -161,6 +161,14 @@ export class VirtualBranch {
|
||||
|
||||
return this.upstreamName || this.name;
|
||||
}
|
||||
|
||||
get ancestorMostConflictedCommit(): DetailedCommit | undefined {
|
||||
if (this.commits.length === 0) return undefined;
|
||||
for (let i = this.commits.length - 1; i >= 0; i--) {
|
||||
const commit = this.commits[i];
|
||||
if (commit?.conflicted) return commit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Used for dependency injection
|
||||
|
@ -107,6 +107,10 @@ export class VirtualBranchService {
|
||||
this.projectMetrics.setMetric('locked_hunk_count', lockedHunks.length);
|
||||
this.projectMetrics.setMetric('file_count', files.length);
|
||||
this.projectMetrics.setMetric('virtual_branch_count', branches.length);
|
||||
this.projectMetrics.setMetric(
|
||||
'max_stack_count',
|
||||
Math.max(...branches.map((b) => b.series.length))
|
||||
);
|
||||
} catch (err: unknown) {
|
||||
console.error(err);
|
||||
}
|
||||
|
58
packages/shared/README.md
Normal file
58
packages/shared/README.md
Normal file
@ -0,0 +1,58 @@
|
||||
# create-svelte
|
||||
|
||||
Everything you need to build a Svelte library, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
|
||||
|
||||
Read more about creating a library [in the docs](https://kit.svelte.dev/docs/packaging).
|
||||
|
||||
## Creating a project
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
```bash
|
||||
# create a new project in the current directory
|
||||
npm create svelte@latest
|
||||
|
||||
# create a new project in my-app
|
||||
npm create svelte@latest my-app
|
||||
```
|
||||
|
||||
## Developing
|
||||
|
||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
|
||||
# or start the server and open the app in a new browser tab
|
||||
npm run dev -- --open
|
||||
```
|
||||
|
||||
Everything inside `src/lib` is part of your library, everything inside `src/routes` can be used as a showcase or preview app.
|
||||
|
||||
## Building
|
||||
|
||||
To build your library:
|
||||
|
||||
```bash
|
||||
npm run package
|
||||
```
|
||||
|
||||
To create a production version of your showcase app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
|
||||
|
||||
## Publishing
|
||||
|
||||
Go into the `package.json` and give your package the desired name through the `"name"` option. Also consider adding a `"license"` field and point it to a `LICENSE` file which you can create from a template (one popular option is the [MIT license](https://opensource.org/license/mit/)).
|
||||
|
||||
To publish your library to [npm](https://www.npmjs.com):
|
||||
|
||||
```bash
|
||||
npm publish
|
||||
```
|
68
packages/shared/package.json
Normal file
68
packages/shared/package.json
Normal file
@ -0,0 +1,68 @@
|
||||
{
|
||||
"name": "@gitbutler/shared",
|
||||
"version": "0.0.1",
|
||||
"description": "UI Elements shared between GitButler Web and Desktop",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"check": "svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "pnpm check --watch",
|
||||
"package": "pnpm run --sequential \"/^package:.*/\"",
|
||||
"package:svelte": "svelte-kit sync && svelte-package",
|
||||
"prepublishOnly": "pnpm run package",
|
||||
"prepare": "svelte-kit sync",
|
||||
"test": "vitest run --mode development",
|
||||
"test:watch": "vitest --watch --mode development"
|
||||
},
|
||||
"exports": {
|
||||
"./*.svelte": {
|
||||
"svelte": "./dist/*.svelte",
|
||||
"types": "./dist/*.svelte.d.ts"
|
||||
},
|
||||
"./*": {
|
||||
"import": "./dist/*.js",
|
||||
"types": "./dist/*.d.ts"
|
||||
},
|
||||
"./*.css": {
|
||||
"import": "./dist/styles/*.css"
|
||||
},
|
||||
"./*.json": {
|
||||
"import": "./dist/*.json",
|
||||
"types": "./dist/*.json"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"!dist/**/*.test.*",
|
||||
"!dist/**/*.spec.*"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"svelte": "^4.0.0 || ^5.0.0-0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@gitbutler/ui": "workspace:*",
|
||||
"@csstools/postcss-bundler": "^1.0.15",
|
||||
"@sveltejs/adapter-static": "catalog:svelte",
|
||||
"@sveltejs/kit": "catalog:svelte",
|
||||
"@sveltejs/package": "^2.3.2",
|
||||
"@sveltejs/vite-plugin-svelte": "catalog:svelte",
|
||||
"@terrazzo/cli": "^0.0.11",
|
||||
"@terrazzo/plugin-css": "^0.0.9",
|
||||
"@types/postcss-pxtorem": "^6.0.3",
|
||||
"@vitest/browser": "^2.0.5",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"cpy-cli": "^5.0.0",
|
||||
"date-fns": "^2.30.0",
|
||||
"playwright": "^1.46.1",
|
||||
"postcss": "^8.4.38",
|
||||
"postcss-cli": "^11.0.0",
|
||||
"postcss-minify": "^1.1.0",
|
||||
"postcss-nesting": "^12.1.5",
|
||||
"postcss-pxtorem": "^6.1.0",
|
||||
"rimraf": "^6.0.1",
|
||||
"svelte": "catalog:svelte",
|
||||
"svelte-check": "catalog:svelte",
|
||||
"vite": "catalog:",
|
||||
"vitest": "^2.0.5"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
23
packages/shared/postcss.config.js
Normal file
23
packages/shared/postcss.config.js
Normal file
@ -0,0 +1,23 @@
|
||||
import postcssBundler from '@csstools/postcss-bundler';
|
||||
import autoprefixer from 'autoprefixer';
|
||||
import postcssMinify from 'postcss-minify';
|
||||
import postcssNesting from 'postcss-nesting';
|
||||
import pxToRem from 'postcss-pxtorem';
|
||||
|
||||
export default {
|
||||
plugins: [
|
||||
pxToRem({
|
||||
rootValue: 16,
|
||||
unitPrecision: 5,
|
||||
propList: ['*'],
|
||||
selectorBlackList: [],
|
||||
replace: true,
|
||||
mediaQuery: false,
|
||||
minPixelValue: 0
|
||||
}),
|
||||
autoprefixer(),
|
||||
postcssNesting(),
|
||||
postcssBundler(),
|
||||
postcssMinify()
|
||||
]
|
||||
};
|
13
packages/shared/src/app.d.ts
vendored
Normal file
13
packages/shared/src/app.d.ts
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface PageState {}
|
||||
// interface Platform {}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
12
packages/shared/src/app.html
Normal file
12
packages/shared/src/app.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div>%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
7
packages/shared/src/index.test.ts
Normal file
7
packages/shared/src/index.test.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('sum test', () => {
|
||||
it('adds 1 + 2 to equal 3', () => {
|
||||
expect(1 + 2).toBe(3);
|
||||
});
|
||||
});
|
4
packages/shared/src/lib/index.ts
Normal file
4
packages/shared/src/lib/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
// Reexport your entry components here
|
||||
export function foo() {
|
||||
return 'foo';
|
||||
}
|
3
packages/shared/src/routes/+page.svelte
Normal file
3
packages/shared/src/routes/+page.svelte
Normal file
@ -0,0 +1,3 @@
|
||||
<h1>Welcome to your library project</h1>
|
||||
<p>Create your package using @sveltejs/package and preview/showcase your work with SvelteKit</p>
|
||||
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
|
BIN
packages/shared/static/favicon.png
Normal file
BIN
packages/shared/static/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
22
packages/shared/svelte.config.js
Normal file
22
packages/shared/svelte.config.js
Normal file
@ -0,0 +1,22 @@
|
||||
import staticAdapter from '@sveltejs/adapter-static';
|
||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
preprocess: vitePreprocess({ script: true }),
|
||||
kit: {
|
||||
adapter: staticAdapter({
|
||||
pages: 'build',
|
||||
assets: 'build',
|
||||
fallback: 'index.html',
|
||||
precompress: true,
|
||||
strict: false
|
||||
})
|
||||
},
|
||||
compilerOptions: {
|
||||
css: 'injected',
|
||||
enableSourcemap: true
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
40
packages/shared/terrazzo.config.js
Normal file
40
packages/shared/terrazzo.config.js
Normal file
@ -0,0 +1,40 @@
|
||||
import { defineConfig } from '@terrazzo/cli';
|
||||
import css from '@terrazzo/plugin-css';
|
||||
|
||||
function pxToRem(token) {
|
||||
if (token.$type === 'dimension' && token.$value.slice(-2) === 'px') {
|
||||
return token.$value.slice(0, -2) / 16 + 'rem';
|
||||
}
|
||||
}
|
||||
|
||||
function clearFxPrefix(id) {
|
||||
if (id.includes('fx.')) {
|
||||
return id.replace('fx.', '').replace('.', '-');
|
||||
}
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
tokens: './src/lib/data/design-tokens.json',
|
||||
outDir: './src/styles/core',
|
||||
plugins: [
|
||||
css({
|
||||
filename: 'design-tokens.css',
|
||||
modeSelectors: [
|
||||
{
|
||||
mode: 'dark',
|
||||
selectors: [':root.dark']
|
||||
}
|
||||
],
|
||||
p3: false,
|
||||
transform: pxToRem,
|
||||
generateName(variableId) {
|
||||
return clearFxPrefix(variableId);
|
||||
},
|
||||
utility: {
|
||||
bg: ['clr.bg.*'],
|
||||
text: ['clr.text.*'],
|
||||
border: ['clr.border.*']
|
||||
}
|
||||
})
|
||||
]
|
||||
});
|
32
packages/shared/tsconfig.json
Normal file
32
packages/shared/tsconfig.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"extends": "./.svelte-kit/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"lib": ["dom", "dom.iterable", "ES2021"],
|
||||
"allowJs": true,
|
||||
"checkJs": false,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"experimentalDecorators": true
|
||||
},
|
||||
"include": [
|
||||
".svelte-kit/ambient.d.ts",
|
||||
".svelte-kit/non-ambient.d.ts",
|
||||
".svelte-kit/types/**/$types.d.ts",
|
||||
"terrazzo.config.js",
|
||||
"postcss.config.js",
|
||||
"vite.config.js",
|
||||
"vite.config.ts",
|
||||
"vitest.workspace.ts",
|
||||
"src/**/*.js",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.svelte",
|
||||
"tests/**/*.js",
|
||||
"tests/**/*.ts",
|
||||
"tests/**/*.svelte"
|
||||
]
|
||||
}
|
9
packages/shared/vite.config.ts
Normal file
9
packages/shared/vite.config.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()],
|
||||
test: {
|
||||
include: ['src/**/*.{test,spec}.{js,ts}']
|
||||
}
|
||||
});
|
@ -139,6 +139,9 @@ importers:
|
||||
'@codemirror/legacy-modes':
|
||||
specifier: ^6.4.0
|
||||
version: 6.4.0
|
||||
'@gitbutler/shared':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/shared
|
||||
'@gitbutler/ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/ui
|
||||
@ -336,6 +339,81 @@ importers:
|
||||
specifier: 'catalog:'
|
||||
version: 5.2.13(@types/node@22.3.0)
|
||||
|
||||
packages/shared:
|
||||
devDependencies:
|
||||
'@csstools/postcss-bundler':
|
||||
specifier: ^1.0.15
|
||||
version: 1.0.15(postcss@8.4.39)
|
||||
'@gitbutler/ui':
|
||||
specifier: workspace:*
|
||||
version: link:../ui
|
||||
'@sveltejs/adapter-static':
|
||||
specifier: catalog:svelte
|
||||
version: 3.0.4(@sveltejs/kit@2.5.25(@sveltejs/vite-plugin-svelte@4.0.0-next.6(svelte@5.0.0-next.243)(vite@5.2.13(@types/node@22.3.0)))(svelte@5.0.0-next.243)(vite@5.2.13(@types/node@22.3.0)))
|
||||
'@sveltejs/kit':
|
||||
specifier: catalog:svelte
|
||||
version: 2.5.25(@sveltejs/vite-plugin-svelte@4.0.0-next.6(svelte@5.0.0-next.243)(vite@5.2.13(@types/node@22.3.0)))(svelte@5.0.0-next.243)(vite@5.2.13(@types/node@22.3.0))
|
||||
'@sveltejs/package':
|
||||
specifier: ^2.3.2
|
||||
version: 2.3.2(svelte@5.0.0-next.243)(typescript@5.4.5)
|
||||
'@sveltejs/vite-plugin-svelte':
|
||||
specifier: catalog:svelte
|
||||
version: 4.0.0-next.6(svelte@5.0.0-next.243)(vite@5.2.13(@types/node@22.3.0))
|
||||
'@terrazzo/cli':
|
||||
specifier: ^0.0.11
|
||||
version: 0.0.11
|
||||
'@terrazzo/plugin-css':
|
||||
specifier: ^0.0.9
|
||||
version: 0.0.9(@terrazzo/cli@0.0.11)
|
||||
'@types/postcss-pxtorem':
|
||||
specifier: ^6.0.3
|
||||
version: 6.0.3
|
||||
'@vitest/browser':
|
||||
specifier: ^2.0.5
|
||||
version: 2.0.5(playwright@1.46.1)(typescript@5.4.5)(vitest@2.0.5)(webdriverio@8.40.2)
|
||||
autoprefixer:
|
||||
specifier: ^10.4.19
|
||||
version: 10.4.19(postcss@8.4.39)
|
||||
cpy-cli:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
date-fns:
|
||||
specifier: ^2.30.0
|
||||
version: 2.30.0
|
||||
playwright:
|
||||
specifier: ^1.46.1
|
||||
version: 1.46.1
|
||||
postcss:
|
||||
specifier: ^8.4.38
|
||||
version: 8.4.39
|
||||
postcss-cli:
|
||||
specifier: ^11.0.0
|
||||
version: 11.0.0(postcss@8.4.39)
|
||||
postcss-minify:
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0(postcss@8.4.39)
|
||||
postcss-nesting:
|
||||
specifier: ^12.1.5
|
||||
version: 12.1.5(postcss@8.4.39)
|
||||
postcss-pxtorem:
|
||||
specifier: ^6.1.0
|
||||
version: 6.1.0(postcss@8.4.39)
|
||||
rimraf:
|
||||
specifier: ^6.0.1
|
||||
version: 6.0.1
|
||||
svelte:
|
||||
specifier: catalog:svelte
|
||||
version: 5.0.0-next.243
|
||||
svelte-check:
|
||||
specifier: catalog:svelte
|
||||
version: 4.0.1(svelte@5.0.0-next.243)(typescript@5.4.5)
|
||||
vite:
|
||||
specifier: 'catalog:'
|
||||
version: 5.2.13(@types/node@22.3.0)
|
||||
vitest:
|
||||
specifier: ^2.0.5
|
||||
version: 2.0.5(@types/node@22.3.0)(@vitest/browser@2.0.5)(@vitest/ui@2.0.5)(happy-dom@14.12.3)(jsdom@24.1.1)
|
||||
|
||||
packages/ui:
|
||||
devDependencies:
|
||||
'@csstools/postcss-bundler':
|
||||
|
12
turbo.json
12
turbo.json
@ -2,10 +2,11 @@
|
||||
"$schema": "https://turborepo.org/schema.json",
|
||||
"tasks": {
|
||||
"package": {
|
||||
"dependsOn": ["^package"],
|
||||
"outputs": ["dist/**"]
|
||||
},
|
||||
"build": {
|
||||
"dependsOn": ["^package"],
|
||||
"dependsOn": ["package"],
|
||||
"passThroughEnv": ["SENTRY_AUTH_TOKEN", "GITHUB_TOKEN"],
|
||||
"env": ["SENTRY_RELEASE"],
|
||||
"outputs": [
|
||||
@ -17,20 +18,19 @@
|
||||
]
|
||||
},
|
||||
"dev": {
|
||||
"dependsOn": ["@gitbutler/ui#package"],
|
||||
"dependsOn": ["package"],
|
||||
"cache": false,
|
||||
"persistent": true
|
||||
},
|
||||
"check": {
|
||||
"dependsOn": ["@gitbutler/ui#package"]
|
||||
"dependsOn": ["package"]
|
||||
},
|
||||
"playwright:install": {},
|
||||
"test": {
|
||||
"dependsOn": ["@gitbutler/ui#package", "playwright:install"]
|
||||
"dependsOn": ["package", "playwright:install"]
|
||||
},
|
||||
"//#globallint": {
|
||||
// Root rules require dependencies to manually be listed https://github.com/vercel/turbo/discussions/7481
|
||||
"dependsOn": ["@gitbutler/ui#package"]
|
||||
"dependsOn": ["@gitbutler/ui#package", "@gitbutler/shared#package"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user