feat: resolve all 22 items in Features and Bugs.txt and complete UI polish
This commit is contained in:
@@ -72,6 +72,11 @@ export function usePubScriptEditor(options: PubScriptEditorHookOptions = {}) {
|
||||
const editor = useEditor({
|
||||
editable,
|
||||
extensions: pubScriptExtensions,
|
||||
editorProps: {
|
||||
attributes: {
|
||||
class: "ps-editor-content",
|
||||
},
|
||||
},
|
||||
...(content !== undefined ? { content } : {}),
|
||||
...useEditorOptions,
|
||||
});
|
||||
|
||||
@@ -17,7 +17,14 @@
|
||||
import StarterKit from "@tiptap/starter-kit";
|
||||
import { TextStyle } from "@tiptap/extension-text-style";
|
||||
|
||||
import { Editor as TipTapEditor, getSchema, type Content } from "@tiptap/core";
|
||||
import {
|
||||
Editor as TipTapEditor,
|
||||
Extension,
|
||||
Mark,
|
||||
getSchema,
|
||||
mergeAttributes,
|
||||
type Content,
|
||||
} from "@tiptap/core";
|
||||
|
||||
import SceneBreakNode from "./nodes/SceneBreak.js";
|
||||
import FootnoteInline from "./nodes/FootnoteInline.js";
|
||||
@@ -37,6 +44,90 @@ import {
|
||||
colorAttribute,
|
||||
} from "./constants.js";
|
||||
|
||||
/**
|
||||
* Inline highlight mark (`<mark class="ps-mark-highlight">`).
|
||||
*/
|
||||
export const HighlightMark = Mark.create({
|
||||
name: "highlight",
|
||||
parseHTML() {
|
||||
return [{ tag: "mark" }];
|
||||
},
|
||||
renderHTML({ HTMLAttributes }) {
|
||||
return ["mark", mergeAttributes({ class: "ps-mark-highlight" }, HTMLAttributes), 0];
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Inline superscript mark (`<sup>`).
|
||||
*/
|
||||
export const SuperscriptMark = Mark.create({
|
||||
name: "superscript",
|
||||
excludes: "subscript",
|
||||
parseHTML() {
|
||||
return [{ tag: "sup" }];
|
||||
},
|
||||
renderHTML({ HTMLAttributes }) {
|
||||
return ["sup", HTMLAttributes, 0];
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Inline subscript mark (`<sub>`).
|
||||
*/
|
||||
export const SubscriptMark = Mark.create({
|
||||
name: "subscript",
|
||||
excludes: "superscript",
|
||||
parseHTML() {
|
||||
return [{ tag: "sub" }];
|
||||
},
|
||||
renderHTML({ HTMLAttributes }) {
|
||||
return ["sub", HTMLAttributes, 0];
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Block-level text alignment extension (`left` | `center` | `right` | `justify`)
|
||||
* applied to paragraphs, headings, and blockquotes.
|
||||
*/
|
||||
export const TextAlignExtension = Extension.create({
|
||||
name: "textAlign",
|
||||
addGlobalAttributes() {
|
||||
return [
|
||||
{
|
||||
types: ["heading", "paragraph", "blockquote"],
|
||||
attributes: {
|
||||
textAlign: {
|
||||
default: "left",
|
||||
parseHTML: (element: HTMLElement) => element.style.textAlign || "left",
|
||||
renderHTML: (attributes: { textAlign?: string }) => {
|
||||
if (!attributes.textAlign || attributes.textAlign === "left") {
|
||||
return {};
|
||||
}
|
||||
return { style: `text-align: ${attributes.textAlign}` };
|
||||
},
|
||||
},
|
||||
lineHeight: {
|
||||
default: null,
|
||||
parseHTML: (element: HTMLElement) => element.style.lineHeight || null,
|
||||
renderHTML: (attributes: { lineHeight?: string | null }) => {
|
||||
if (!attributes.lineHeight) return {};
|
||||
return { style: `line-height: ${attributes.lineHeight}` };
|
||||
},
|
||||
},
|
||||
textIndent: {
|
||||
default: null,
|
||||
parseHTML: (element: HTMLElement) => element.style.textIndent || null,
|
||||
renderHTML: (attributes: { textIndent?: string | null }) => {
|
||||
if (!attributes.textIndent) return {};
|
||||
return { style: `text-indent: ${attributes.textIndent}` };
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* The full extension list, registered once. Order matters: base kits first,
|
||||
* then text styling, then PubScript nodes.
|
||||
@@ -44,8 +135,28 @@ import {
|
||||
export const pubScriptExtensions = [
|
||||
StarterKit,
|
||||
TextStyle.extend({
|
||||
addAttributes: colorAttribute,
|
||||
addAttributes() {
|
||||
return {
|
||||
...colorAttribute(),
|
||||
fontFamily: {
|
||||
default: null,
|
||||
parseHTML: (element: HTMLElement) => element.style.fontFamily || null,
|
||||
renderHTML: (attributes: { fontFamily?: string | null }) =>
|
||||
attributes.fontFamily ? { style: `font-family: ${attributes.fontFamily}` } : {},
|
||||
},
|
||||
fontSize: {
|
||||
default: null,
|
||||
parseHTML: (element: HTMLElement) => element.style.fontSize || null,
|
||||
renderHTML: (attributes: { fontSize?: string | null }) =>
|
||||
attributes.fontSize ? { style: `font-size: ${attributes.fontSize}` } : {},
|
||||
},
|
||||
};
|
||||
},
|
||||
}),
|
||||
HighlightMark,
|
||||
SuperscriptMark,
|
||||
SubscriptMark,
|
||||
TextAlignExtension,
|
||||
SceneBreakNode,
|
||||
FootnoteInline,
|
||||
FootnoteArea,
|
||||
|
||||
Reference in New Issue
Block a user