5.7 KiB
@aomao/plugin-heading
Heading style plugin
Installation
$ yarn add @aomao/plugin-heading
Add to engine
import Engine, {EngineInterface} from'@aomao/engine';
import Heading from'@aomao/plugin-heading';
new Engine(...,{ plugins:[Heading] })
Optional
Anchor
A copyable anchor button appears on the left side of the title after it is turned on
showAnchor?: boolean;
Triggered when the copy anchor is clicked, the id value of the current title is passed in, the returned content will be written to the user's pasteboard, and the current url+id will be returned by default
anchorCopy?:(id:string) => string
hot key
//hot key
hotkey?: {
h1?: string;//Title 1, default mod+opt+1
h2?: string;//Title 2, default mod+opt+2
h3?: string;//Title 3, default mod+opt+3
h4?: string;//Title 4, default mod+opt+4
h5?: string;//Title 5, default mod+opt+5
h6?: string;//Title 6, default mod+opt+6
};
//Use configuration
new Engine(...,{
config:{
"heading":{
//Modify shortcut keys
hotkey:{
h1: "shortcut key"
}
}
}
})
Markdown
Support markdown by default, pass in false
to close
The heading plugin markdown syntax is #
##
###
####
#####
######
markdown?: boolean;//enabled by default, false off
//Use configuration
new Engine(...,{
config:{
"heading":{
//Close markdown
markdown:false
}
}
})
Disable mark plugin style effect
You can disable the mark plug-in effect under the title, ['fontsize','bold'] is disabled by default, and filter out these plug-in styles in the case of splitting, pasting, etc.
disableMark?: Array<string> //mark plugin name collection
Type to be enabled (h1 h2 h3 h4 h5 h6)
Can define the node types required by h1-h6, if not defined, all are supported
Markdown will also be invalid after setting
enableTypes?: Array<string>
In addition, you may also need to configure the heading plugin of the items attribute in the toolbar
{
type:'dropdown',
name:'heading',
items: [
{
key: "p",
className:'heading-item-p',
content: "Body"
},
{
key: "h1",
className:'heading-item-h1',
content: "Title 1"
}
]
}
Command
When p
is passed in or the current heading style is consistent with the current passed value, the heading will be canceled
//Use command to execute the plug-in and pass in the required parameters
engine.command.execute(
'heading',
'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p',
);
//Use command to execute query current status, return string | undefined, return "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p"
engine.command.queryState('heading');
Outline
Generate headline outline data
Need to import the Outline
class from @aomao/plugin-heading
import { Outline } from '@aomao/plugin-heading';
normalize
Normalize the title node data into a structure with depth levels
/**
* Normalize heading data into a structure with depth levels
* After normalization, the structure of each element is:
* {
* id: string, // id
* title: string, // title
* level: number, // Title level
* domNode: Node, // dom node
* depth: number // display depth
*}
* The depth algorithm is consistent with that of Google Docs
*-Effect: h1 -> h4 assign a fixed depth to ensure that the final level depth of the title of the same level is the same
*-Algorithm: Find out the title level of the document; assign the indentation depth in descending order of level;
* @param {Element[]}headings heading standard DOM node array
*
* @return {Array} title node array
*/
normalize(headings: Array<Element>): OutlineData[];
getFromDom
Extract outline from DOM node
/**
* Extract outline from DOM node
* @param {Element} rootNode root node
* @return {Array}
*/
getFromDom(rootNode: Element): OutlineData[];
Examples
例子
import React, { useRef, useEffect, useState, useCallback } from 'react';
import { $, EditorInterface } from '@aomao/engine';
import { Outline, OutlineData } from '@aomao/plugin-heading';
type Props = {
editor: EditorInterface;
};
const outline = new Outline();
const Toc: React.FC<Props> = ({ editor }) => {
const rootRef = useRef<HTMLDivElement | null>(null);
const [datas, setDatas] = useState<Array<OutlineData>>([]);
useEffect(() => {
const onChange = () => {
//Get outline data
const data = getTocData();
setDatas(data);
};
//Binding editor value change event
editor.on('change', onChange);
setTimeout(() => {
onChange();
}, 50);
return () => editor.off('change', onChange);
}, [editor]);
const getTocData = useCallback(() => {
// Extract the title Dom node that meets the structural requirements
let nodes: Array<Element> = [];
const { card } = editor;
editor.container.find('h1,h2,h3,h4,h5,h6').each((child) => {
const node = $(child);
// The title in the Card is not included in the outline
if (card.closest(node)) {
return;
}
// Non-first-level in-depth titles, not included in the outline
if (!node.parent()?.isRoot()) {
return;
}
nodes.push(node.get<Element>()!);
});
return outline.normalize(nodes);
}, []);
return (
<div className="data-toc-wrapper">
<div className="data-toc-title">大纲</div>
<div className="data-toc" ref={rootRef}>
{datas.map((data, index) => {
return (
<a
key={index}
href={'#' + data.id}
className={`data-toc-item data-toc-item-${data.depth}`}
>
{data.text}
</a>
);
})}
</div>
</div>
);
};
export default Toc;