mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-18 02:31:56 +10:00
Compare commits
21 Commits
v4.5.0
...
1296e6bd45
| Author | SHA1 | Date | |
|---|---|---|---|
| 1296e6bd45 | |||
| d883edb51f | |||
| 6fcb7a4845 | |||
| 213f96b189 | |||
| e8d6d4ad3a | |||
| 87370cfdf0 | |||
| 112a644927 | |||
| 2977e3528a | |||
| 21fd079f94 | |||
| 9bdc61b50d | |||
| 2de24d5b55 | |||
| 1cba9d0fb9 | |||
| 8f532bf4a6 | |||
| 4efdabd475 | |||
| 8803101dcd | |||
| a4a9381b65 | |||
| 618d42019e | |||
| d9b56cfb5b | |||
| 5624dc4f83 | |||
| 313fe47050 | |||
| 772332661f |
81
.env.example
Normal file
81
.env.example
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# Environment
|
||||||
|
NODE_ENV=development
|
||||||
|
|
||||||
|
# Ports
|
||||||
|
PORT=3000
|
||||||
|
|
||||||
|
# URLs
|
||||||
|
# These URLs must reference a publicly accessible domain or IP address, not a docker container ID (depending on your compose setup)
|
||||||
|
PUBLIC_URL=http://localhost:3000
|
||||||
|
STORAGE_URL=http://localhost:9000/default # default is the bucket name specified in the STORAGE_BUCKET variable
|
||||||
|
|
||||||
|
# Database (Prisma/PostgreSQL)
|
||||||
|
# This can be swapped out to use any other database, like MySQL
|
||||||
|
# Note: This is used only in the compose.yml file
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
POSTGRES_DB=postgres
|
||||||
|
POSTGRES_USER=postgres
|
||||||
|
POSTGRES_PASSWORD=postgres
|
||||||
|
|
||||||
|
# Database (Prisma/PostgreSQL)
|
||||||
|
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres?schema=public
|
||||||
|
|
||||||
|
# Authentication Secrets
|
||||||
|
# generated with `openssl rand -base64 64`
|
||||||
|
ACCESS_TOKEN_SECRET=access_token_secret
|
||||||
|
REFRESH_TOKEN_SECRET=refresh_token_secret
|
||||||
|
|
||||||
|
# Chrome Browser (for printing)
|
||||||
|
# generated with `openssl rand -hex 32`
|
||||||
|
CHROME_PORT=8080
|
||||||
|
CHROME_TOKEN=chrome_token
|
||||||
|
CHROME_URL=ws://localhost:8080
|
||||||
|
# Launch puppeteer with flag to ignore https errors
|
||||||
|
# CHROME_IGNORE_HTTPS_ERRORS=true
|
||||||
|
|
||||||
|
# Mail Server (for e-mails)
|
||||||
|
# For testing, you can use https://ethereal.email/create
|
||||||
|
MAIL_FROM=noreply@localhost
|
||||||
|
# SMTP_URL=smtp://username:password@smtp.ethereal.email:587
|
||||||
|
|
||||||
|
# Storage
|
||||||
|
STORAGE_ENDPOINT=localhost
|
||||||
|
STORAGE_PORT=9000
|
||||||
|
STORAGE_REGION=us-east-1
|
||||||
|
STORAGE_BUCKET=default
|
||||||
|
STORAGE_ACCESS_KEY=minioadmin
|
||||||
|
STORAGE_SECRET_KEY=minioadmin
|
||||||
|
STORAGE_USE_SSL=false
|
||||||
|
STORAGE_SKIP_BUCKET_CHECK=false
|
||||||
|
|
||||||
|
# Nx Cloud (Optional)
|
||||||
|
# NX_CLOUD_ACCESS_TOKEN=
|
||||||
|
|
||||||
|
# Crowdin (Optional)
|
||||||
|
# CROWDIN_PROJECT_ID=
|
||||||
|
# CROWDIN_PERSONAL_TOKEN=
|
||||||
|
|
||||||
|
# Feature Flags (Optional)
|
||||||
|
# DISABLE_SIGNUPS=false
|
||||||
|
# DISABLE_EMAIL_AUTH=false
|
||||||
|
|
||||||
|
# GitHub (OAuth, Optional)
|
||||||
|
# GITHUB_CLIENT_ID=
|
||||||
|
# GITHUB_CLIENT_SECRET=
|
||||||
|
# GITHUB_CALLBACK_URL=http://localhost:5173/api/auth/github/callback
|
||||||
|
|
||||||
|
# Google (OAuth, Optional)
|
||||||
|
# GOOGLE_CLIENT_ID=
|
||||||
|
# GOOGLE_CLIENT_SECRET=
|
||||||
|
# GOOGLE_CALLBACK_URL=http://localhost:5173/api/auth/google/callback
|
||||||
|
|
||||||
|
# OpenID (Optional)
|
||||||
|
# VITE_OPENID_NAME=
|
||||||
|
# OPENID_AUTHORIZATION_URL=
|
||||||
|
# OPENID_CALLBACK_URL=http://localhost:5173/api/auth/openid/callback
|
||||||
|
# OPENID_CLIENT_ID=
|
||||||
|
# OPENID_CLIENT_SECRET=
|
||||||
|
# OPENID_ISSUER=
|
||||||
|
# OPENID_SCOPE=openid profile email
|
||||||
|
# OPENID_TOKEN_URL=
|
||||||
|
# OPENID_USER_INFO_URL=
|
||||||
2
.vscode/extensions.json
vendored
2
.vscode/extensions.json
vendored
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"recommendations": ["nrwl.angular-console", "esbenp.prettier-vscode", "dbaeumer.vscode-eslint"]
|
"recommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"]
|
||||||
}
|
}
|
||||||
|
|||||||
18
README.md
18
README.md
@ -38,16 +38,20 @@ Start creating your standout resume with Reactive Resume today!
|
|||||||
## Templates
|
## Templates
|
||||||
|
|
||||||
| Azurill | Bronzor | Chikorita |
|
| Azurill | Bronzor | Chikorita |
|
||||||
| ------------------------------------------------------------ | ----------------------------------------------------------- | ----------------------------------------------------------- |
|
| ----------------------------------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
||||||
| <img src="https://i.imgur.com/jKgo04C.jpeg" width="200px" /> | <img src="https://i.imgur.com/DFNQZP2.jpg" width="200px" /> | <img src="https://i.imgur.com/Dwv8Y7f.jpg" width="200px" /> |
|
| <img src="./apps/client/public/templates/jpg/azurill.jpg" width="200px" /> | <img src="./apps/client/public/templates/jpg/bronzor.jpg" width="200px" /> | <img src="./apps/client/public/templates/jpg/chikorita.jpg" width="200px" /> |
|
||||||
|
|
||||||
| Ditto | Kakuna | Nosepass |
|
| Ditto | Gengar | Glalie |
|
||||||
| ----------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- |
|
| -------------------------------------------------------------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------- |
|
||||||
| <img src="https://i.imgur.com/6c5lASL.jpg" width="200px" /> | <img src="https://i.imgur.com/268ML3t.jpg" width="200px" /> | <img src="https://i.imgur.com/npRLsPS.jpg" width="200px" /> |
|
| <img src="./apps/client/public/templates/jpg/ditto.jpg" width="200px" /> | <img src="./apps/client/public/templates/jpg/gengar.jpg" width="200px" /> | <img src="./apps/client/public/templates/jpg/glalie.jpg" width="200px" /> |
|
||||||
|
|
||||||
|
| Kakuna | Leafish | Nosepass |
|
||||||
|
| ---------------------------------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------ |
|
||||||
|
| <img src="./apps/client/public/templates/jpg/kakuna.jpg" width="200px" /> | <img src="./apps/client/public/templates/jpg/leafish.jpg" width="200px" /> | <img src="./apps/client/public/templates/jpg/nosepass.jpg" width="200px" /> |
|
||||||
|
|
||||||
| Onyx | Pikachu | Rhyhorn |
|
| Onyx | Pikachu | Rhyhorn |
|
||||||
| ----------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- |
|
| ------------------------------------------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------------- |
|
||||||
| <img src="https://i.imgur.com/cxplXOW.jpg" width="200px" /> | <img src="https://i.imgur.com/Y9f7qsh.jpg" width="200px" /> | <img src="https://i.imgur.com/h4kQxy2.jpg" width="200px" /> |
|
| <img src="./apps/client/public/templates/jpg/onyx.jpg" width="200px" /> | <img src="./apps/client/public/templates/jpg/pikachu.jpg" width="200px" /> | <img src="./apps/client/public/templates/jpg/rhyhorn.jpg" width="200px" /> |
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|||||||
@ -14,8 +14,8 @@ export const Picture = ({ className }: PictureProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
src={picture.url}
|
|
||||||
alt="Profile"
|
alt="Profile"
|
||||||
|
src={picture.url}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative z-20 object-cover",
|
"relative z-20 object-cover",
|
||||||
picture.effects.border && "border-primary",
|
picture.effects.border && "border-primary",
|
||||||
|
|||||||
@ -531,6 +531,11 @@ const mapSectionToComponent = (section: SectionKey) => {
|
|||||||
case "education": {
|
case "education": {
|
||||||
return <Education />;
|
return <Education />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "summary": {
|
||||||
|
return <Summary />;
|
||||||
|
}
|
||||||
|
|
||||||
case "awards": {
|
case "awards": {
|
||||||
return <Awards />;
|
return <Awards />;
|
||||||
}
|
}
|
||||||
@ -592,8 +597,6 @@ export const Gengar = ({ columns, isFirstPage = false }: TemplateProps) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={cn("main group", sidebar.length > 0 ? "col-span-2" : "col-span-3")}>
|
<div className={cn("main group", sidebar.length > 0 ? "col-span-2" : "col-span-3")}>
|
||||||
{isFirstPage && <Summary />}
|
|
||||||
|
|
||||||
<div className="p-custom space-y-4">
|
<div className="p-custom space-y-4">
|
||||||
{main.map((section) => (
|
{main.map((section) => (
|
||||||
<Fragment key={section}>{mapSectionToComponent(section)}</Fragment>
|
<Fragment key={section}>{mapSectionToComponent(section)}</Fragment>
|
||||||
|
|||||||
67
apps/client/public/funding.json
Normal file
67
apps/client/public/funding.json
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://fundingjson.org/schema/v1.0.0/funding.schema.json",
|
||||||
|
"version": "v1.0.0",
|
||||||
|
"entity": {
|
||||||
|
"type": "individual",
|
||||||
|
"role": "maintainer",
|
||||||
|
"name": "Amruth Pillai",
|
||||||
|
"email": "im.amruth@gmail.com",
|
||||||
|
"description": "Software Engineer",
|
||||||
|
"webpageUrl": {
|
||||||
|
"url": "https://rxresu.me/funding.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"projects": [
|
||||||
|
{
|
||||||
|
"guid": "reactive-resume",
|
||||||
|
"name": "Reactive Resume",
|
||||||
|
"description": "A free and open-source resume builder that simplifies the process of creating, updating, and sharing your resume.",
|
||||||
|
"webpageUrl": {
|
||||||
|
"url": "https://rxresu.me"
|
||||||
|
},
|
||||||
|
"repositoryUrl": {
|
||||||
|
"url": "https://github.com/AmruthPillai/Reactive-Resume"
|
||||||
|
},
|
||||||
|
"licenses": ["spdx:MIT"],
|
||||||
|
"tags": ["data", "design", "productivity", "resume-builder"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"funding": {
|
||||||
|
"plans": [
|
||||||
|
{
|
||||||
|
"guid": "sponsor",
|
||||||
|
"status": "active",
|
||||||
|
"name": "Sponsor",
|
||||||
|
"description": "Support the project on a recurring basis by becoming a sponsor.",
|
||||||
|
"amount": 10,
|
||||||
|
"currency": "EUR",
|
||||||
|
"frequency": "monthly",
|
||||||
|
"channels": ["github", "open-collective"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"guid": "donation",
|
||||||
|
"status": "active",
|
||||||
|
"name": "Donation",
|
||||||
|
"description": "Show your support for the project by making a one-time donation.",
|
||||||
|
"amount": 0,
|
||||||
|
"currency": "EUR",
|
||||||
|
"frequency": "one-time",
|
||||||
|
"channels": ["github", "open-collective"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"channels": [
|
||||||
|
{
|
||||||
|
"guid": "github",
|
||||||
|
"type": "payment-provider",
|
||||||
|
"description": "GitHub Sponsors",
|
||||||
|
"address": "https://github.com/sponsors/AmruthPillai"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"guid": "open-collective",
|
||||||
|
"type": "payment-provider",
|
||||||
|
"description": "Open Collective",
|
||||||
|
"address": "https://opencollective.com/reactive-resume"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,7 +8,7 @@ msgstr ""
|
|||||||
"Language: hi\n"
|
"Language: hi\n"
|
||||||
"Project-Id-Version: reactive-resume\n"
|
"Project-Id-Version: reactive-resume\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"PO-Revision-Date: 2025-10-01 09:32\n"
|
"PO-Revision-Date: 2025-10-08 00:10\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: Hindi\n"
|
"Language-Team: Hindi\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,6 @@
|
|||||||
import { Logger, Module } from "@nestjs/common";
|
import { Module } from "@nestjs/common";
|
||||||
import { ConfigService } from "@nestjs/config";
|
import { ConfigService } from "@nestjs/config";
|
||||||
import {
|
import { PrismaModule, providePrismaClientExceptionFilter } from "nestjs-prisma";
|
||||||
loggingMiddleware,
|
|
||||||
PrismaModule,
|
|
||||||
PrismaService,
|
|
||||||
providePrismaClientExceptionFilter,
|
|
||||||
} from "nestjs-prisma";
|
|
||||||
|
|
||||||
import { Config } from "@/server/config/schema";
|
import { Config } from "@/server/config/schema";
|
||||||
|
|
||||||
@ -16,14 +11,6 @@ import { Config } from "@/server/config/schema";
|
|||||||
inject: [ConfigService],
|
inject: [ConfigService],
|
||||||
useFactory: (configService: ConfigService<Config>) => ({
|
useFactory: (configService: ConfigService<Config>) => ({
|
||||||
prismaOptions: { datasourceUrl: configService.get("DATABASE_URL") },
|
prismaOptions: { datasourceUrl: configService.get("DATABASE_URL") },
|
||||||
middlewares: [
|
|
||||||
loggingMiddleware({
|
|
||||||
logLevel: "debug", // only in development
|
|
||||||
logger: new Logger(PrismaService.name),
|
|
||||||
logMessage: (query) =>
|
|
||||||
`[Query] ${query.model}.${query.action} - ${query.executionTime}ms`,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -139,22 +139,6 @@ export class PrinterService {
|
|||||||
page.waitForSelector('[data-page="1"]', { timeout: 15_000 }),
|
page.waitForSelector('[data-page="1"]', { timeout: 15_000 }),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (resume.data.basics.picture.url) {
|
|
||||||
await page.waitForSelector('img[alt="Profile"]');
|
|
||||||
await page.evaluate(() =>
|
|
||||||
Promise.all(
|
|
||||||
// eslint-disable-next-line unicorn/prefer-spread
|
|
||||||
Array.from(document.images).map((img) => {
|
|
||||||
if (img.complete) return Promise.resolve();
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
// eslint-disable-next-line unicorn/prefer-add-event-listener
|
|
||||||
img.onload = img.onerror = resolve;
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const pagesBuffer: Buffer[] = [];
|
const pagesBuffer: Buffer[] = [];
|
||||||
|
|
||||||
const processPage = async (index: number) => {
|
const processPage = async (index: number) => {
|
||||||
|
|||||||
1
funding.json
Symbolic link
1
funding.json
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
apps/client/public/funding.json
|
||||||
@ -151,6 +151,7 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive("bold")}
|
pressed={editor.isActive("bold")}
|
||||||
disabled={!editor.can().chain().toggleBold().run()}
|
disabled={!editor.can().chain().toggleBold().run()}
|
||||||
|
data-state={editor.isActive("bold") ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().toggleBold().run()}
|
onPressedChange={() => editor.chain().focus().toggleBold().run()}
|
||||||
>
|
>
|
||||||
<TextBIcon />
|
<TextBIcon />
|
||||||
@ -163,6 +164,7 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive("italic")}
|
pressed={editor.isActive("italic")}
|
||||||
disabled={!editor.can().chain().focus().toggleItalic().run()}
|
disabled={!editor.can().chain().focus().toggleItalic().run()}
|
||||||
|
data-state={editor.isActive("italic") ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().toggleItalic().run()}
|
onPressedChange={() => editor.chain().focus().toggleItalic().run()}
|
||||||
>
|
>
|
||||||
<TextItalicIcon />
|
<TextItalicIcon />
|
||||||
@ -175,6 +177,7 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive("strike")}
|
pressed={editor.isActive("strike")}
|
||||||
disabled={!editor.can().chain().focus().toggleStrike().run()}
|
disabled={!editor.can().chain().focus().toggleStrike().run()}
|
||||||
|
data-state={editor.isActive("strike") ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().toggleStrike().run()}
|
onPressedChange={() => editor.chain().focus().toggleStrike().run()}
|
||||||
>
|
>
|
||||||
<TextStrikethroughIcon />
|
<TextStrikethroughIcon />
|
||||||
@ -187,6 +190,7 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive("underline")}
|
pressed={editor.isActive("underline")}
|
||||||
disabled={!editor.can().chain().focus().toggleUnderline().run()}
|
disabled={!editor.can().chain().focus().toggleUnderline().run()}
|
||||||
|
data-state={editor.isActive("underline") ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().toggleUnderline().run()}
|
onPressedChange={() => editor.chain().focus().toggleUnderline().run()}
|
||||||
>
|
>
|
||||||
<TextAUnderlineIcon />
|
<TextAUnderlineIcon />
|
||||||
@ -199,12 +203,15 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive("highlight")}
|
pressed={editor.isActive("highlight")}
|
||||||
disabled={!editor.can().chain().focus().toggleHighlight().run()}
|
disabled={!editor.can().chain().focus().toggleHighlight().run()}
|
||||||
|
data-state={editor.isActive("highlight") ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().toggleHighlight().run()}
|
onPressedChange={() => editor.chain().focus().toggleHighlight().run()}
|
||||||
>
|
>
|
||||||
<HighlighterCircleIcon />
|
<HighlighterCircleIcon />
|
||||||
</Toggle>
|
</Toggle>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
|
<div className="my-auto h-5 w-px bg-border" />
|
||||||
|
|
||||||
<Tooltip content="Hyperlink">
|
<Tooltip content="Hyperlink">
|
||||||
<Button type="button" size="sm" variant="ghost" className="px-2" onClick={setLink}>
|
<Button type="button" size="sm" variant="ghost" className="px-2" onClick={setLink}>
|
||||||
<LinkSimpleIcon />
|
<LinkSimpleIcon />
|
||||||
@ -217,6 +224,7 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive("code")}
|
pressed={editor.isActive("code")}
|
||||||
disabled={!editor.can().chain().focus().toggleCode().run()}
|
disabled={!editor.can().chain().focus().toggleCode().run()}
|
||||||
|
data-state={editor.isActive("code") ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().toggleCode().run()}
|
onPressedChange={() => editor.chain().focus().toggleCode().run()}
|
||||||
>
|
>
|
||||||
<CodeIconImport />
|
<CodeIconImport />
|
||||||
@ -229,18 +237,22 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive("codeBlock")}
|
pressed={editor.isActive("codeBlock")}
|
||||||
disabled={!editor.can().chain().focus().toggleCodeBlock().run()}
|
disabled={!editor.can().chain().focus().toggleCodeBlock().run()}
|
||||||
|
data-state={editor.isActive("codeBlock") ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().toggleCodeBlock().run()}
|
onPressedChange={() => editor.chain().focus().toggleCodeBlock().run()}
|
||||||
>
|
>
|
||||||
<CodeBlockIconImport />
|
<CodeBlockIconImport />
|
||||||
</Toggle>
|
</Toggle>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
|
<div className="my-auto h-5 w-px bg-border" />
|
||||||
|
|
||||||
<Tooltip content="Heading 1">
|
<Tooltip content="Heading 1">
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive("heading", { level: 1 })}
|
pressed={editor.isActive("heading", { level: 1 })}
|
||||||
disabled={!editor.can().chain().focus().toggleHeading({ level: 1 }).run()}
|
disabled={!editor.can().chain().focus().toggleHeading({ level: 1 }).run()}
|
||||||
|
data-state={editor.isActive("heading", { level: 1 }) ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
onPressedChange={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||||
>
|
>
|
||||||
<TextHOneIcon />
|
<TextHOneIcon />
|
||||||
@ -253,6 +265,7 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive("heading", { level: 2 })}
|
pressed={editor.isActive("heading", { level: 2 })}
|
||||||
disabled={!editor.can().chain().focus().toggleHeading({ level: 2 }).run()}
|
disabled={!editor.can().chain().focus().toggleHeading({ level: 2 }).run()}
|
||||||
|
data-state={editor.isActive("heading", { level: 2 }) ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
onPressedChange={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||||
>
|
>
|
||||||
<TextHTwoIcon />
|
<TextHTwoIcon />
|
||||||
@ -265,6 +278,7 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive("heading", { level: 3 })}
|
pressed={editor.isActive("heading", { level: 3 })}
|
||||||
disabled={!editor.can().chain().focus().toggleHeading({ level: 3 }).run()}
|
disabled={!editor.can().chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
|
data-state={editor.isActive("heading", { level: 3 }) ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
onPressedChange={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
>
|
>
|
||||||
<TextHThreeIcon />
|
<TextHThreeIcon />
|
||||||
@ -276,18 +290,22 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
size="sm"
|
size="sm"
|
||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive("paragraph")}
|
pressed={editor.isActive("paragraph")}
|
||||||
|
data-state={editor.isActive("paragraph") ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().setParagraph().run()}
|
onPressedChange={() => editor.chain().focus().setParagraph().run()}
|
||||||
>
|
>
|
||||||
<ParagraphIconImport />
|
<ParagraphIconImport />
|
||||||
</Toggle>
|
</Toggle>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
|
<div className="my-auto h-5 w-px bg-border" />
|
||||||
|
|
||||||
<Tooltip content="Align Left">
|
<Tooltip content="Align Left">
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive({ textAlign: "left" })}
|
pressed={editor.isActive({ textAlign: "left" })}
|
||||||
disabled={!editor.can().chain().focus().setTextAlign("left").run()}
|
disabled={!editor.can().chain().focus().setTextAlign("left").run()}
|
||||||
|
data-state={editor.isActive({ textAlign: "left" }) ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().setTextAlign("left").run()}
|
onPressedChange={() => editor.chain().focus().setTextAlign("left").run()}
|
||||||
>
|
>
|
||||||
<TextAlignLeftIcon />
|
<TextAlignLeftIcon />
|
||||||
@ -300,6 +318,7 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive({ textAlign: "center" })}
|
pressed={editor.isActive({ textAlign: "center" })}
|
||||||
disabled={!editor.can().chain().focus().setTextAlign("center").run()}
|
disabled={!editor.can().chain().focus().setTextAlign("center").run()}
|
||||||
|
data-state={editor.isActive({ textAlign: "center" }) ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().setTextAlign("center").run()}
|
onPressedChange={() => editor.chain().focus().setTextAlign("center").run()}
|
||||||
>
|
>
|
||||||
<TextAlignCenterIcon />
|
<TextAlignCenterIcon />
|
||||||
@ -312,6 +331,7 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive({ textAlign: "right" })}
|
pressed={editor.isActive({ textAlign: "right" })}
|
||||||
disabled={!editor.can().chain().focus().setTextAlign("right").run()}
|
disabled={!editor.can().chain().focus().setTextAlign("right").run()}
|
||||||
|
data-state={editor.isActive({ textAlign: "right" }) ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().setTextAlign("right").run()}
|
onPressedChange={() => editor.chain().focus().setTextAlign("right").run()}
|
||||||
>
|
>
|
||||||
<TextAlignRightIcon />
|
<TextAlignRightIcon />
|
||||||
@ -324,18 +344,22 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive({ textAlign: "justify" })}
|
pressed={editor.isActive({ textAlign: "justify" })}
|
||||||
disabled={!editor.can().chain().focus().setTextAlign("justify").run()}
|
disabled={!editor.can().chain().focus().setTextAlign("justify").run()}
|
||||||
|
data-state={editor.isActive({ textAlign: "justify" }) ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().setTextAlign("justify").run()}
|
onPressedChange={() => editor.chain().focus().setTextAlign("justify").run()}
|
||||||
>
|
>
|
||||||
<TextAlignJustifyIcon />
|
<TextAlignJustifyIcon />
|
||||||
</Toggle>
|
</Toggle>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
|
<div className="my-auto h-5 w-px bg-border" />
|
||||||
|
|
||||||
<Tooltip content="Bullet List">
|
<Tooltip content="Bullet List">
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive("bulletList")}
|
pressed={editor.isActive("bulletList")}
|
||||||
disabled={!editor.can().chain().focus().toggleBulletList().run()}
|
disabled={!editor.can().chain().focus().toggleBulletList().run()}
|
||||||
|
data-state={editor.isActive("bulletList") ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().toggleBulletList().run()}
|
onPressedChange={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
>
|
>
|
||||||
<ListBulletsIcon />
|
<ListBulletsIcon />
|
||||||
@ -348,6 +372,7 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
pressed={editor.isActive("orderedList")}
|
pressed={editor.isActive("orderedList")}
|
||||||
disabled={!editor.can().chain().focus().toggleOrderedList().run()}
|
disabled={!editor.can().chain().focus().toggleOrderedList().run()}
|
||||||
|
data-state={editor.isActive("orderedList") ? "on" : "off"}
|
||||||
onPressedChange={() => editor.chain().focus().toggleOrderedList().run()}
|
onPressedChange={() => editor.chain().focus().toggleOrderedList().run()}
|
||||||
>
|
>
|
||||||
<ListNumbersIcon />
|
<ListNumbersIcon />
|
||||||
@ -380,6 +405,8 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
|
<div className="my-auto h-5 w-px bg-border" />
|
||||||
|
|
||||||
<Popover>
|
<Popover>
|
||||||
<Tooltip content="Insert Image">
|
<Tooltip content="Insert Image">
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
@ -419,6 +446,8 @@ const Toolbar = ({ editor }: { editor: Editor }) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
|
<div className="my-auto h-5 w-px bg-border" />
|
||||||
|
|
||||||
<Tooltip content="Undo">
|
<Tooltip content="Undo">
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|||||||
76
package.json
76
package.json
@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "@reactive-resume/source",
|
"name": "@reactive-resume/source",
|
||||||
"description": "A free and open-source resume builder that simplifies the process of creating, updating, and sharing your resume.",
|
"description": "A free and open-source resume builder that simplifies the process of creating, updating, and sharing your resume.",
|
||||||
"version": "4.5.0",
|
"version": "4.5.3",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"private": true,
|
"private": true,
|
||||||
"packageManager": "pnpm@10.17.1+sha512.17c560fca4867ae9473a3899ad84a88334914f379be46d455cbf92e5cf4b39d34985d452d2583baf19967fa76cb5c17bc9e245529d0b98745721aa7200ecaf7a",
|
"packageManager": "pnpm@10.20.0",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Amruth Pillai",
|
"name": "Amruth Pillai",
|
||||||
"url": "https://amruthpillai.com",
|
"url": "https://amruthpillai.com",
|
||||||
@ -32,8 +32,8 @@
|
|||||||
"messages:extract": "pnpm exec lingui extract --clean --overwrite"
|
"messages:extract": "pnpm exec lingui extract --clean --overwrite"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.28.4",
|
"@babel/core": "^7.28.5",
|
||||||
"@babel/preset-react": "^7.27.1",
|
"@babel/preset-react": "^7.28.5",
|
||||||
"@lingui/cli": "^4.14.1",
|
"@lingui/cli": "^4.14.1",
|
||||||
"@lingui/conf": "^4.14.1",
|
"@lingui/conf": "^4.14.1",
|
||||||
"@lingui/swc-plugin": "^4.1.0",
|
"@lingui/swc-plugin": "^4.1.0",
|
||||||
@ -57,13 +57,13 @@
|
|||||||
"@tailwindcss/container-queries": "^0.1.1",
|
"@tailwindcss/container-queries": "^0.1.1",
|
||||||
"@tailwindcss/forms": "^0.5.10",
|
"@tailwindcss/forms": "^0.5.10",
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@tanstack/eslint-plugin-query": "^5.91.0",
|
"@tanstack/eslint-plugin-query": "^5.91.2",
|
||||||
"@testing-library/react": "^16.3.0",
|
"@testing-library/react": "^16.3.0",
|
||||||
"@tiptap/core": "^2.26.2",
|
"@tiptap/core": "^2.27.1",
|
||||||
"@types/async-retry": "^1.4.9",
|
"@types/async-retry": "^1.4.9",
|
||||||
"@types/bcryptjs": "^2.4.6",
|
"@types/bcryptjs": "^2.4.6",
|
||||||
"@types/cookie-parser": "^1.4.9",
|
"@types/cookie-parser": "^1.4.10",
|
||||||
"@types/express": "^4.17.23",
|
"@types/express": "^4.17.25",
|
||||||
"@types/express-session": "^1.18.2",
|
"@types/express-session": "^1.18.2",
|
||||||
"@types/file-saver": "^2.0.7",
|
"@types/file-saver": "^2.0.7",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
@ -71,23 +71,23 @@
|
|||||||
"@types/lodash.get": "^4.4.9",
|
"@types/lodash.get": "^4.4.9",
|
||||||
"@types/lodash.set": "^4.3.9",
|
"@types/lodash.set": "^4.3.9",
|
||||||
"@types/multer": "^1.4.13",
|
"@types/multer": "^1.4.13",
|
||||||
"@types/node": "^22.18.8",
|
"@types/node": "^22.19.0",
|
||||||
"@types/nodemailer": "^6.4.20",
|
"@types/nodemailer": "^6.4.21",
|
||||||
"@types/papaparse": "^5.3.16",
|
"@types/papaparse": "^5.3.16",
|
||||||
"@types/passport": "^1.0.17",
|
"@types/passport": "^1.0.17",
|
||||||
"@types/passport-github2": "^1.2.9",
|
"@types/passport-github2": "^1.2.9",
|
||||||
"@types/passport-google-oauth20": "^2.0.16",
|
"@types/passport-google-oauth20": "^2.0.17",
|
||||||
"@types/passport-local": "^1.0.38",
|
"@types/passport-local": "^1.0.38",
|
||||||
"@types/passport-openidconnect": "^0.1.3",
|
"@types/passport-openidconnect": "^0.1.3",
|
||||||
"@types/prismjs": "^1.26.5",
|
"@types/prismjs": "^1.26.5",
|
||||||
"@types/react": "^18.3.25",
|
"@types/react": "^18.3.26",
|
||||||
"@types/react-dom": "^18.3.7",
|
"@types/react-dom": "^18.3.7",
|
||||||
"@types/react-is": "^18.3.1",
|
"@types/react-is": "^18.3.1",
|
||||||
"@types/retry": "^0.12.5",
|
"@types/retry": "^0.12.5",
|
||||||
"@types/sanitize-html": "^2.16.0",
|
"@types/sanitize-html": "^2.16.0",
|
||||||
"@types/webfontloader": "^1.6.38",
|
"@types/webfontloader": "^1.6.38",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.45.0",
|
"@typescript-eslint/eslint-plugin": "^8.46.3",
|
||||||
"@typescript-eslint/parser": "^8.45.0",
|
"@typescript-eslint/parser": "^8.46.3",
|
||||||
"@vitejs/plugin-react": "^4.7.0",
|
"@vitejs/plugin-react": "^4.7.0",
|
||||||
"@vitejs/plugin-react-swc": "^3.11.0",
|
"@vitejs/plugin-react-swc": "^3.11.0",
|
||||||
"@vitest/coverage-v8": "^2.1.9",
|
"@vitest/coverage-v8": "^2.1.9",
|
||||||
@ -114,14 +114,14 @@
|
|||||||
"postcss-import": "^16.1.1",
|
"postcss-import": "^16.1.1",
|
||||||
"postcss-nested": "^6.2.0",
|
"postcss-nested": "^6.2.0",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.14",
|
"prettier-plugin-tailwindcss": "^0.7.1",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.18",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"ts-jest": "^29.4.4",
|
"ts-jest": "^29.4.5",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"turbo": "^2.5.8",
|
"turbo": "^2.6.0",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"vite": "^5.4.20",
|
"vite": "^5.4.21",
|
||||||
"vite-plugin-dts": "^4.5.4",
|
"vite-plugin-dts": "^4.5.4",
|
||||||
"vitest": "^2.1.9"
|
"vitest": "^2.1.9"
|
||||||
},
|
},
|
||||||
@ -147,7 +147,7 @@
|
|||||||
"@nestjs/serve-static": "^4.0.2",
|
"@nestjs/serve-static": "^4.0.2",
|
||||||
"@nestjs/swagger": "^7.4.2",
|
"@nestjs/swagger": "^7.4.2",
|
||||||
"@nestjs/terminus": "^10.3.0",
|
"@nestjs/terminus": "^10.3.0",
|
||||||
"@paralleldrive/cuid2": "^2.2.2",
|
"@paralleldrive/cuid2": "^2.3.1",
|
||||||
"@phosphor-icons/react": "^2.1.10",
|
"@phosphor-icons/react": "^2.1.10",
|
||||||
"@prisma/client": "^5.22.0",
|
"@prisma/client": "^5.22.0",
|
||||||
"@radix-ui/react-accordion": "^1.2.12",
|
"@radix-ui/react-accordion": "^1.2.12",
|
||||||
@ -176,32 +176,32 @@
|
|||||||
"@radix-ui/react-visually-hidden": "^1.2.3",
|
"@radix-ui/react-visually-hidden": "^1.2.3",
|
||||||
"@sindresorhus/slugify": "^2.2.1",
|
"@sindresorhus/slugify": "^2.2.1",
|
||||||
"@swc/helpers": "^0.5.17",
|
"@swc/helpers": "^0.5.17",
|
||||||
"@tanstack/react-query": "^5.90.2",
|
"@tanstack/react-query": "^5.90.6",
|
||||||
"@tiptap/extension-highlight": "^2.26.2",
|
"@tiptap/extension-highlight": "^2.27.1",
|
||||||
"@tiptap/extension-image": "^2.26.2",
|
"@tiptap/extension-image": "^2.27.1",
|
||||||
"@tiptap/extension-link": "^2.26.2",
|
"@tiptap/extension-link": "^2.27.1",
|
||||||
"@tiptap/extension-text-align": "^2.26.2",
|
"@tiptap/extension-text-align": "^2.27.1",
|
||||||
"@tiptap/extension-underline": "^2.26.2",
|
"@tiptap/extension-underline": "^2.27.1",
|
||||||
"@tiptap/pm": "^2.26.2",
|
"@tiptap/pm": "^2.27.1",
|
||||||
"@tiptap/react": "^2.26.2",
|
"@tiptap/react": "^2.27.1",
|
||||||
"@tiptap/starter-kit": "^2.26.1",
|
"@tiptap/starter-kit": "^2.27.1",
|
||||||
"@types/passport-jwt": "^4.0.1",
|
"@types/passport-jwt": "^4.0.1",
|
||||||
"async-retry": "^1.3.3",
|
"async-retry": "^1.3.3",
|
||||||
"axios": "^1.12.2",
|
"axios": "^1.13.1",
|
||||||
"axios-auth-refresh": "^3.3.6",
|
"axios-auth-refresh": "^3.3.6",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "^1.1.1",
|
"cmdk": "^1.1.1",
|
||||||
"cookie-parser": "^1.4.7",
|
"cookie-parser": "^1.4.7",
|
||||||
"dayjs": "^1.11.18",
|
"dayjs": "^1.11.19",
|
||||||
"deepmerge": "^4.3.1",
|
"deepmerge": "^4.3.1",
|
||||||
"express-session": "^1.18.2",
|
"express-session": "^1.18.2",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"framer-motion": "^11.18.2",
|
"framer-motion": "^11.18.2",
|
||||||
"fuzzy": "^0.1.3",
|
"fuzzy": "^0.1.3",
|
||||||
"helmet": "^7.2.0",
|
"helmet": "^7.2.0",
|
||||||
"immer": "^10.1.3",
|
"immer": "^10.2.0",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"lodash.debounce": "^4.0.8",
|
"lodash.debounce": "^4.0.8",
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
@ -209,9 +209,9 @@
|
|||||||
"minio": "^8.0.6",
|
"minio": "^8.0.6",
|
||||||
"nest-raven": "^10.1.0",
|
"nest-raven": "^10.1.0",
|
||||||
"nestjs-minio-client": "^2.2.0",
|
"nestjs-minio-client": "^2.2.0",
|
||||||
"nestjs-prisma": "^0.25.0",
|
"nestjs-prisma": "^0.26.0",
|
||||||
"nestjs-zod": "^3.0.0",
|
"nestjs-zod": "^3.0.0",
|
||||||
"nodemailer": "^6.10.1",
|
"nodemailer": "^7.0.10",
|
||||||
"openai": "^4.104.0",
|
"openai": "^4.104.0",
|
||||||
"otplib": "^12.0.1",
|
"otplib": "^12.0.1",
|
||||||
"papaparse": "^5.5.3",
|
"papaparse": "^5.5.3",
|
||||||
@ -230,10 +230,10 @@
|
|||||||
"react-colorful": "^5.6.1",
|
"react-colorful": "^5.6.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-helmet-async": "^2.0.5",
|
"react-helmet-async": "^2.0.5",
|
||||||
"react-hook-form": "^7.63.0",
|
"react-hook-form": "^7.66.0",
|
||||||
"react-parallax-tilt": "^1.7.309",
|
"react-parallax-tilt": "^1.7.311",
|
||||||
"react-resizable-panels": "^2.1.9",
|
"react-resizable-panels": "^2.1.9",
|
||||||
"react-router": "^7.9.3",
|
"react-router": "^7.9.5",
|
||||||
"react-simple-code-editor": "^0.14.1",
|
"react-simple-code-editor": "^0.14.1",
|
||||||
"react-zoom-pan-pinch": "^3.7.0",
|
"react-zoom-pan-pinch": "^3.7.0",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
@ -243,7 +243,7 @@
|
|||||||
"tailwind-merge": "^2.6.0",
|
"tailwind-merge": "^2.6.0",
|
||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"unique-names-generator": "^4.7.1",
|
"unique-names-generator": "^4.7.1",
|
||||||
"use-breakpoint": "^4.0.6",
|
"use-breakpoint": "^4.0.10",
|
||||||
"use-keyboard-shortcut": "^1.1.6",
|
"use-keyboard-shortcut": "^1.1.6",
|
||||||
"usehooks-ts": "^3.1.1",
|
"usehooks-ts": "^3.1.1",
|
||||||
"webfontloader": "^1.6.28",
|
"webfontloader": "^1.6.28",
|
||||||
|
|||||||
3109
pnpm-lock.yaml
generated
3109
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user