diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 94305bb..0000000 --- a/.dockerignore +++ /dev/null @@ -1,51 +0,0 @@ -# Dependencies -node_modules -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Next.js -.next/ -out/ - -# Production -build - -# Misc -.DS_Store -*.tsbuildinfo - -# Debug -*.log - -# Local env files -.env*.local -.env - -# Vercel -.vercel - -# TypeScript -*.tsbuildinfo -next-env.d.ts - -# IDE -.vscode -.idea - -# Git -.git -.gitignore -README.md - -# Docker -Dockerfile* -docker-compose* -.dockerignore - -# Testing -coverage -.nyc_output - -# Linting -.eslintcache diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index aab6617..0000000 --- a/Dockerfile +++ /dev/null @@ -1,69 +0,0 @@ -# Use the official Node.js 18 Alpine image as base -FROM node:18-alpine AS base - -# Install dependencies only when needed -FROM base AS deps -# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. -RUN apk add --no-cache libc6-compat -WORKDIR /app - -# Install dependencies based on the preferred package manager -COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ -RUN \ - if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ - elif [ -f package-lock.json ]; then npm ci; \ - elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \ - else echo "Lockfile not found." && exit 1; \ - fi - -# Rebuild the source code only when needed -FROM base AS builder -WORKDIR /app -COPY --from=deps /app/node_modules ./node_modules -COPY . . - -# Next.js collects completely anonymous telemetry data about general usage. -# Learn more here: https://nextjs.org/telemetry -# Uncomment the following line in case you want to disable telemetry during the build. -ENV NEXT_TELEMETRY_DISABLED 1 - -RUN \ - if [ -f yarn.lock ]; then yarn run build; \ - elif [ -f package-lock.json ]; then npm run build; \ - elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \ - else echo "Lockfile not found." && exit 1; \ - fi - -# Production image, copy all the files and run next -FROM base AS runner -WORKDIR /app - -ENV NODE_ENV production -# Uncomment the following line in case you want to disable telemetry during runtime. -ENV NEXT_TELEMETRY_DISABLED 1 - -RUN addgroup --system --gid 1001 nodejs -RUN adduser --system --uid 1001 nextjs - -COPY --from=builder /app/public ./public - -# Set the correct permission for prerender cache -RUN mkdir .next -RUN chown nextjs:nodejs .next - -# Automatically leverage output traces to reduce image size -# https://nextjs.org/docs/advanced-features/output-file-tracing -COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ -COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static - -USER nextjs - -EXPOSE 3000 - -ENV PORT 3000 -# set hostname to localhost -ENV HOSTNAME "0.0.0.0" - -# server.js is created by next build from the standalone output -# https://nextjs.org/docs/pages/api-reference/next-config-js/output -CMD ["node", "server.js"] diff --git a/Makefile b/Makefile deleted file mode 100644 index 3ef133c..0000000 --- a/Makefile +++ /dev/null @@ -1,54 +0,0 @@ -# Makefile for Markdown Editor Docker operations - -.PHONY: help build run stop clean logs shell health - -# Default target -help: - @echo "Available commands:" - @echo " build - Build the Docker image" - @echo " run - Run the application with docker-compose" - @echo " run-prod - Run with nginx reverse proxy" - @echo " stop - Stop all containers" - @echo " clean - Remove containers and images" - @echo " logs - Show application logs" - @echo " shell - Open shell in the app container" - @echo " health - Check application health" - -# Build the Docker image -build: - docker-compose build --no-cache - -# Run the application (development) -run: - docker-compose up -d markdown-editor - @echo "Application is running at http://localhost:3000" - -# Run with production setup (nginx + app) -run-prod: - docker-compose --profile production up -d - @echo "Application is running at http://localhost (port 80)" - -# Stop all containers -stop: - docker-compose down - -# Clean up containers and images -clean: - docker-compose down --rmi all --volumes --remove-orphans - docker system prune -f - -# Show logs -logs: - docker-compose logs -f markdown-editor - -# Open shell in the app container -shell: - docker-compose exec markdown-editor sh - -# Check application health -health: - @echo "Checking application health..." - @curl -f http://localhost:3000/api/health || echo "Health check failed" - -# Quick development cycle -dev: stop build run logs diff --git a/app/api/health/route.ts b/app/api/health/route.ts deleted file mode 100644 index d223eeb..0000000 --- a/app/api/health/route.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { NextResponse } from "next/server" - -export async function GET() { - return NextResponse.json( - { - status: "healthy", - timestamp: new Date().toISOString(), - service: "markdown-editor", - }, - { status: 200 }, - ) -} diff --git a/app/globals.css b/app/globals.css index ac68442..8a4f5a6 100644 --- a/app/globals.css +++ b/app/globals.css @@ -2,85 +2,50 @@ @tailwind components; @tailwind utilities; -body { - font-family: Arial, Helvetica, sans-serif; -} - -@layer utilities { - .text-balance { - text-wrap: balance; - } -} - @layer base { :root { --background: 0 0% 100%; - --foreground: 0 0% 3.9%; + --foreground: 222.2 84% 4.9%; --card: 0 0% 100%; - --card-foreground: 0 0% 3.9%; + --card-foreground: 222.2 84% 4.9%; --popover: 0 0% 100%; - --popover-foreground: 0 0% 3.9%; - --primary: 0 0% 9%; - --primary-foreground: 0 0% 98%; - --secondary: 0 0% 96.1%; - --secondary-foreground: 0 0% 9%; - --muted: 0 0% 96.1%; - --muted-foreground: 0 0% 45.1%; - --accent: 0 0% 96.1%; - --accent-foreground: 0 0% 9%; + --popover-foreground: 222.2 84% 4.9%; + --primary: 221.2 83.2% 53.3%; + --primary-foreground: 210 40% 98%; + --secondary: 210 40% 96%; + --secondary-foreground: 222.2 84% 4.9%; + --muted: 210 40% 96%; + --muted-foreground: 215.4 16.3% 46.9%; + --accent: 210 40% 96%; + --accent-foreground: 222.2 84% 4.9%; --destructive: 0 84.2% 60.2%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 89.8%; - --input: 0 0% 89.8%; - --ring: 0 0% 3.9%; - --chart-1: 12 76% 61%; - --chart-2: 173 58% 39%; - --chart-3: 197 37% 24%; - --chart-4: 43 74% 66%; - --chart-5: 27 87% 67%; + --destructive-foreground: 210 40% 98%; + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 221.2 83.2% 53.3%; --radius: 0.5rem; - --sidebar-background: 0 0% 98%; - --sidebar-foreground: 240 5.3% 26.1%; - --sidebar-primary: 240 5.9% 10%; - --sidebar-primary-foreground: 0 0% 98%; - --sidebar-accent: 240 4.8% 95.9%; - --sidebar-accent-foreground: 240 5.9% 10%; - --sidebar-border: 220 13% 91%; - --sidebar-ring: 217.2 91.2% 59.8%; } + .dark { - --background: 0 0% 3.9%; - --foreground: 0 0% 98%; - --card: 0 0% 3.9%; - --card-foreground: 0 0% 98%; - --popover: 0 0% 3.9%; - --popover-foreground: 0 0% 98%; - --primary: 0 0% 98%; - --primary-foreground: 0 0% 9%; - --secondary: 0 0% 14.9%; - --secondary-foreground: 0 0% 98%; - --muted: 0 0% 14.9%; - --muted-foreground: 0 0% 63.9%; - --accent: 0 0% 14.9%; - --accent-foreground: 0 0% 98%; + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + --primary: 217.2 91.2% 59.8%; + --primary-foreground: 222.2 84% 4.9%; + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; --destructive: 0 62.8% 30.6%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 14.9%; - --input: 0 0% 14.9%; - --ring: 0 0% 83.1%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; - --sidebar-background: 240 5.9% 10%; - --sidebar-foreground: 240 4.8% 95.9%; - --sidebar-primary: 224.3 76.3% 48%; - --sidebar-primary-foreground: 0 0% 100%; - --sidebar-accent: 240 3.7% 15.9%; - --sidebar-accent-foreground: 240 4.8% 95.9%; - --sidebar-border: 240 3.7% 15.9%; - --sidebar-ring: 217.2 91.2% 59.8%; + --destructive-foreground: 210 40% 98%; + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 224.3 76.3% 94.1%; } } @@ -92,3 +57,61 @@ body { @apply bg-background text-foreground; } } + +/* Custom prose styles for markdown preview */ +.prose { + @apply max-w-none; +} + +.prose h1 { + @apply text-3xl font-bold mb-4; +} + +.prose h2 { + @apply text-2xl font-semibold mb-3; +} + +.prose h3 { + @apply text-xl font-semibold mb-2; +} + +.prose p { + @apply mb-4 leading-relaxed; +} + +.prose ul { + @apply mb-4; +} + +.prose ol { + @apply mb-4; +} + +.prose li { + @apply mb-2; +} + +.prose blockquote { + @apply border-l-4 pl-4 py-2 my-4 italic; +} + +.prose code { + @apply px-1 py-0.5 rounded text-sm font-mono; +} + +.prose pre { + @apply p-4 rounded-lg overflow-x-auto my-4; +} + +.prose table { + @apply w-full border-collapse my-4; +} + +.prose th, +.prose td { + @apply border px-4 py-2 text-left; +} + +.prose th { + @apply font-semibold; +} diff --git a/app/page.tsx b/app/page.tsx index 7e3b74d..8a9735a 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,59 +1,7 @@ "use client" -import { MarkdownEditor } from "@/components/markdown-editor" -const defaultMarkdown = `# 🚀 Welcome to Markdown Editor +import config from "../tailwind.config" -This is a **modern** markdown editor with *real-time* preview and a **colorful** interface! - -## ✨ Features - -- 🎨 Beautiful split-screen editing -- ⚡ Live preview with instant updates -- 🛠️ Rich formatting toolbar -- 🌈 Modern, colorful UI - -### 💻 Code Example - -\`\`\`javascript -function createAwesome() { - console.log("Building something amazing! 🎉"); - return "success"; -} -\`\`\` - -### 📝 Lists & More - -1. **First priority** - Get things done -2. **Second priority** - Make it beautiful -3. **Third priority** - Share with the world - -- 🎯 Bullet points with style -- 🚀 Another awesome point - - 💡 Nested brilliance - - ⭐ Even more nested goodness - -### 🔗 Links and Media - -[🌟 Visit our GitHub](https://github.com) for more amazing projects! - -> 💬 This is a beautiful blockquote with some **bold** text and *italic* styling. - ---- - -### 📊 Data Table - -| Feature | Status | Priority | -|---------|--------|----------| -| Editor | ✅ Complete | High | -| Preview | ✅ Complete | High | -| Export | 🚧 In Progress | Medium | - -Happy writing! ✨🎉` - -export default function Home() { - return ( -
- -
- ) -} +export default function SyntheticV0PageForDeployment() { + return +} \ No newline at end of file diff --git a/components/markdown-editor.tsx b/components/markdown-editor.tsx deleted file mode 100644 index 59db61d..0000000 --- a/components/markdown-editor.tsx +++ /dev/null @@ -1,98 +0,0 @@ -"use client" - -import { useState, useCallback } from "react" -import { MarkdownToolbar } from "./markdown-toolbar" -import { MarkdownInput } from "./markdown-input" -import { MarkdownPreview } from "./markdown-preview" -import { FileText, Eye, Edit3, Sparkles } from "lucide-react" - -interface MarkdownEditorProps { - initialContent?: string -} - -export function MarkdownEditor({ initialContent = "" }: MarkdownEditorProps) { - const [content, setContent] = useState(initialContent) - const [textareaRef, setTextareaRef] = useState(null) - - const insertText = useCallback( - (before: string, after = "", placeholder = "") => { - if (!textareaRef) return - - const start = textareaRef.selectionStart - const end = textareaRef.selectionEnd - const selectedText = content.substring(start, end) - const textToInsert = selectedText || placeholder - const newText = content.substring(0, start) + before + textToInsert + after + content.substring(end) - - setContent(newText) - - // Set cursor position after insertion - setTimeout(() => { - const newCursorPos = start + before.length + textToInsert.length - textareaRef.setSelectionRange(newCursorPos, newCursorPos) - textareaRef.focus() - }, 0) - }, - [content, textareaRef], - ) - - return ( -
- {/* Header */} -
-
-
-
- - -
-
-

- Markdown Editor -

-

Write • Preview • Create

-
-
-
-
- - {/* Toolbar */} -
- -
- - {/* Editor */} -
- {/* Input Panel */} -
-
-
- -
- Editor -
-
- Live -
-
- -
- - {/* Preview Panel */} -
-
-
- -
- Preview -
-
- Real-time -
-
- -
-
-
- ) -} diff --git a/components/markdown-input.tsx b/components/markdown-input.tsx deleted file mode 100644 index 3d7f0c2..0000000 --- a/components/markdown-input.tsx +++ /dev/null @@ -1,65 +0,0 @@ -"use client" - -import type React from "react" -import { useEffect, useRef } from "react" - -interface MarkdownInputProps { - content: string - onChange: (content: string) => void - onTextareaRef: (ref: HTMLTextAreaElement | null) => void -} - -export function MarkdownInput({ content, onChange, onTextareaRef }: MarkdownInputProps) { - const textareaRef = useRef(null) - - useEffect(() => { - onTextareaRef(textareaRef.current) - }, [onTextareaRef]) - - const handleKeyDown = (e: React.KeyboardEvent) => { - if (e.key === "Tab") { - e.preventDefault() - const start = e.currentTarget.selectionStart - const end = e.currentTarget.selectionEnd - const newContent = content.substring(0, start) + " " + content.substring(end) - onChange(newContent) - - setTimeout(() => { - if (textareaRef.current) { - textareaRef.current.setSelectionRange(start + 2, start + 2) - } - }, 0) - } - } - - return ( -
-