Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: CI

# Builds the workspace on every PR and push to main so broken builds are caught
# before a release is attempted.

on:
push:
branches: [main]
pull_request:
branches: [main]

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build
run: pnpm build

- name: Test
run: pnpm --filter @lexkit/editor test
95 changes: 95 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: Release @lexkit/editor

# Publishes @lexkit/editor to npm whenever its version changes on main.
#
# Flow ("release as you sync"):
# 1. Bump the version in packages/editor/package.json
# (e.g. `pnpm --filter @lexkit/editor version patch`).
# 2. Commit & push to main.
# 3. This workflow builds the package, checks whether that exact version is
# already on npm, and if not, publishes it (with provenance) and cuts a
# GitHub release. Pushes that don't change the version are no-ops.
#
# Setup required once:
# - Add an npm "Automation" access token as the repo secret `NPM_TOKEN`
# (Settings -> Secrets and variables -> Actions -> New repository secret).

on:
push:
branches: [main]
paths:
- "packages/editor/**"
- ".github/workflows/release.yml"
workflow_dispatch: {} # allow manual runs from the Actions tab

concurrency:
group: release-editor
cancel-in-progress: false

permissions:
contents: write # create tags + GitHub releases
id-token: write # REQUIRED for npm provenance (the "Published from GitHub" badge)

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup pnpm
uses: pnpm/action-setup@v4 # version comes from "packageManager" in package.json

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
registry-url: "https://registry.npmjs.org"
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build package
run: pnpm --filter @lexkit/editor build

- name: Test
run: pnpm --filter @lexkit/editor test

- name: Check whether this version is already published
id: check
working-directory: packages/editor
run: |
NAME=$(node -p "require('./package.json').name")
VERSION=$(node -p "require('./package.json').version")
echo "name=$NAME" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
if npm view "$NAME@$VERSION" version >/dev/null 2>&1; then
echo "published=true" >> "$GITHUB_OUTPUT"
echo "::notice::$NAME@$VERSION is already on npm — skipping publish."
else
echo "published=false" >> "$GITHUB_OUTPUT"
echo "::notice::$NAME@$VERSION is not on npm — publishing."
fi

- name: Publish to npm (with provenance)
if: steps.check.outputs.published == 'false'
working-directory: packages/editor
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: "true"
run: pnpm publish --no-git-checks --access public

- name: Tag release and create GitHub Release
if: steps.check.outputs.published == 'false'
env:
GH_TOKEN: ${{ github.token }}
run: |
TAG="editor-v${{ steps.check.outputs.version }}"
git tag "$TAG"
git push origin "$TAG"
gh release create "$TAG" \
--title "@lexkit/editor v${{ steps.check.outputs.version }}" \
--generate-notes
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ npm-debug.log*

*_NOTES.*
.vscode
**/.vscode
**/.vscode
.claude
18 changes: 13 additions & 5 deletions packages/editor/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lexkit/editor",
"version": "0.0.38",
"version": "0.0.39",
"description": "LexKit Editor - A headless, extensible rich text editor built on Lexical",
"type": "module",
"private": false,
Expand All @@ -13,12 +13,19 @@
"require": "./dist/index.js",
"default": "./dist/index.js"
}

},
"files": [
"dist"
],
"publishConfig": {
"access": "public"
},
"scripts": {
"build": "tsup",
"lint": "eslint . --max-warnings 0",
"dev": "tsup --watch"
"dev": "tsup --watch",
"test": "vitest run",
"test:watch": "vitest"
},
"keywords": [
"editor",
Expand All @@ -39,15 +46,16 @@
"url": "https://github.com/novincode/lexkit/issues"
},
"homepage": "https://github.com/novincode/lexkit#readme",
"dependencies": {},
"devDependencies": {
"@repo/eslint-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@types/react": "^19.1.1",
"@types/react-dom": "^19.1.1",
"eslint": "^9.32.0",
"jsdom": "^29.1.1",
"tsup": "^8.0.0",
"typescript": "^5.7.3"
"typescript": "^5.7.3",
"vitest": "^4.1.8"
},
"peerDependencies": {
"@lexical/code": ">=0.34.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function debounce<T extends (...args: any[]) => any>(
func: T,
wait: number,
): (...args: Parameters<T>) => void {
let timeout: NodeJS.Timeout;
let timeout: ReturnType<typeof setTimeout>;
return (...args: Parameters<T>) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), wait);
Expand Down Expand Up @@ -462,7 +462,7 @@ function DraggableBlockPlugin({

// Mouse tracking for handle visibility with smooth positioning
useEffect(() => {
let hideTimeout: NodeJS.Timeout;
let hideTimeout: ReturnType<typeof setTimeout>;

const handleMouseMove = (e: MouseEvent) => {
if (isDragging) return;
Expand Down Expand Up @@ -1001,7 +1001,7 @@ function DraggableBlockPlugin({
const editorElement = editor.getRootElement();
if (!editorElement) return;

let pressTimeout: NodeJS.Timeout | null = null;
let pressTimeout: ReturnType<typeof setTimeout> | null = null;
let startX = 0;
let startY = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ function FloatingToolbarPlugin<TCommands = any, TStates = any>({
func: T,
wait: number,
) => {
let timeout: NodeJS.Timeout;
let timeout: ReturnType<typeof setTimeout>;
return (...args: Parameters<T>) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(() => args), wait);
Expand Down
13 changes: 12 additions & 1 deletion packages/editor/src/extensions/export/transformers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,28 @@ import { HTML_EMBED_MARKDOWN_TRANSFORMER } from "../media/HTMLEmbedExtension";
import { HORIZONTAL_RULE_TRANSFORMER } from "../formatting/HorizontalRuleExtension";
import { UNDERLINE_TRANSFORMER } from "../formatting/UnderlineExtension";
import { TABLE_MARKDOWN_TRANSFORMER } from "../formatting/TableExtension";
import { IMAGE_MARKDOWN_TRANSFORMER } from "../media/ImageExtension";
import {
IMAGE_MARKDOWN_TRANSFORMER,
IMAGE_TEXT_MATCH_TRANSFORMER,
} from "../media/ImageExtension";

/**
* All markdown transformers collected in one place
* Import this array to get all available transformers
*
* Note: images ship two transformers. The element transformer handles
* top-level (block) images, while the text-match transformer handles images
* nested inside other elements (e.g. inside a paragraph after HTML import or
* when placed inline with text). Both are required for images to survive a
* markdown export in every position.
*/
export const ALL_MARKDOWN_TRANSFORMERS = [
HTML_EMBED_MARKDOWN_TRANSFORMER,
HORIZONTAL_RULE_TRANSFORMER,
UNDERLINE_TRANSFORMER,
TABLE_MARKDOWN_TRANSFORMER,
IMAGE_MARKDOWN_TRANSFORMER,
IMAGE_TEXT_MATCH_TRANSFORMER,
];

/**
Expand All @@ -31,4 +41,5 @@ export {
UNDERLINE_TRANSFORMER,
TABLE_MARKDOWN_TRANSFORMER,
IMAGE_MARKDOWN_TRANSFORMER,
IMAGE_TEXT_MATCH_TRANSFORMER,
};
11 changes: 10 additions & 1 deletion packages/editor/src/extensions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,16 @@ export {
} from "./export/MarkdownExtension";

// Media Extensions
export { ImageExtension, imageExtension } from "./media/ImageExtension";
export {
ImageExtension,
imageExtension,
ImageNode,
$createImageNode,
$isImageNode,
IMAGE_MARKDOWN_TRANSFORMER,
IMAGE_TEXT_MATCH_TRANSFORMER,
} from "./media/ImageExtension";
export { ImageTranslator } from "./media/ImageTranslator";
export {
HTMLEmbedExtension,
htmlEmbedExtension,
Expand Down
Loading
Loading