1 |
|
2 |
|
3 |
|
4 | import { omit } from 'lodash';
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | import { __ } from '@wordpress/i18n';
|
10 | import {
|
11 | createBlock,
|
12 | getPhrasingContentSchema,
|
13 | getBlockAttributes,
|
14 | } from '@wordpress/blocks';
|
15 | import { RichText } from '@wordpress/block-editor';
|
16 | import {
|
17 | Path,
|
18 | SVG,
|
19 | } from '@wordpress/components';
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | import edit from './edit';
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 | export function getLevelFromHeadingNodeName( nodeName ) {
|
34 | return Number( nodeName.substr( 1 ) );
|
35 | }
|
36 |
|
37 | const supports = {
|
38 | className: false,
|
39 | anchor: true,
|
40 | };
|
41 |
|
42 | const schema = {
|
43 | content: {
|
44 | type: 'string',
|
45 | source: 'html',
|
46 | selector: 'h1,h2,h3,h4,h5,h6',
|
47 | default: '',
|
48 | },
|
49 | level: {
|
50 | type: 'number',
|
51 | default: 2,
|
52 | },
|
53 | align: {
|
54 | type: 'string',
|
55 | },
|
56 | placeholder: {
|
57 | type: 'string',
|
58 | },
|
59 | };
|
60 |
|
61 | export const name = 'core/heading';
|
62 |
|
63 | export const settings = {
|
64 | title: __( 'Heading' ),
|
65 |
|
66 | description: __( 'Introduce new sections and organize content to help visitors (and search engines) understand the structure of your content.' ),
|
67 |
|
68 | icon: <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><Path d="M5 4v3h5.5v12h3V7H19V4z" /><Path fill="none" d="M0 0h24v24H0V0z" /></SVG>,
|
69 |
|
70 | category: 'common',
|
71 |
|
72 | keywords: [ __( 'title' ), __( 'subtitle' ) ],
|
73 |
|
74 | supports,
|
75 |
|
76 | attributes: schema,
|
77 |
|
78 | transforms: {
|
79 | from: [
|
80 | {
|
81 | type: 'block',
|
82 | blocks: [ 'core/paragraph' ],
|
83 | transform: ( { content } ) => {
|
84 | return createBlock( 'core/heading', {
|
85 | content,
|
86 | } );
|
87 | },
|
88 | },
|
89 | {
|
90 | type: 'raw',
|
91 | selector: 'h1,h2,h3,h4,h5,h6',
|
92 | schema: {
|
93 | h1: { children: getPhrasingContentSchema() },
|
94 | h2: { children: getPhrasingContentSchema() },
|
95 | h3: { children: getPhrasingContentSchema() },
|
96 | h4: { children: getPhrasingContentSchema() },
|
97 | h5: { children: getPhrasingContentSchema() },
|
98 | h6: { children: getPhrasingContentSchema() },
|
99 | },
|
100 | transform( node ) {
|
101 | return createBlock( 'core/heading', {
|
102 | ...getBlockAttributes(
|
103 | 'core/heading',
|
104 | node.outerHTML
|
105 | ),
|
106 | level: getLevelFromHeadingNodeName( node.nodeName ),
|
107 | } );
|
108 | },
|
109 | },
|
110 | ...[ 2, 3, 4, 5, 6 ].map( ( level ) => ( {
|
111 | type: 'prefix',
|
112 | prefix: Array( level + 1 ).join( '#' ),
|
113 | transform( content ) {
|
114 | return createBlock( 'core/heading', {
|
115 | level,
|
116 | content,
|
117 | } );
|
118 | },
|
119 | } ) ),
|
120 | ],
|
121 | to: [
|
122 | {
|
123 | type: 'block',
|
124 | blocks: [ 'core/paragraph' ],
|
125 | transform: ( { content } ) => {
|
126 | return createBlock( 'core/paragraph', {
|
127 | content,
|
128 | } );
|
129 | },
|
130 | },
|
131 | ],
|
132 | },
|
133 |
|
134 | deprecated: [
|
135 | {
|
136 | supports,
|
137 | attributes: {
|
138 | ...omit( schema, [ 'level' ] ),
|
139 | nodeName: {
|
140 | type: 'string',
|
141 | source: 'property',
|
142 | selector: 'h1,h2,h3,h4,h5,h6',
|
143 | property: 'nodeName',
|
144 | default: 'H2',
|
145 | },
|
146 | },
|
147 | migrate( attributes ) {
|
148 | const { nodeName, ...migratedAttributes } = attributes;
|
149 |
|
150 | return {
|
151 | ...migratedAttributes,
|
152 | level: getLevelFromHeadingNodeName( nodeName ),
|
153 | };
|
154 | },
|
155 | save( { attributes } ) {
|
156 | const { align, nodeName, content } = attributes;
|
157 |
|
158 | return (
|
159 | <RichText.Content
|
160 | tagName={ nodeName.toLowerCase() }
|
161 | style={ { textAlign: align } }
|
162 | value={ content }
|
163 | />
|
164 | );
|
165 | },
|
166 | },
|
167 | ],
|
168 |
|
169 | merge( attributes, attributesToMerge ) {
|
170 | return {
|
171 | content: ( attributes.content || '' ) + ( attributesToMerge.content || '' ),
|
172 | };
|
173 | },
|
174 |
|
175 | edit,
|
176 |
|
177 | save( { attributes } ) {
|
178 | const { align, level, content } = attributes;
|
179 | const tagName = 'h' + level;
|
180 |
|
181 | return (
|
182 | <RichText.Content
|
183 | tagName={ tagName }
|
184 | style={ { textAlign: align } }
|
185 | value={ content }
|
186 | />
|
187 | );
|
188 | },
|
189 | };
|