mirror of
https://github.com/dream-num/univer.git
synced 2026-09-21 13:50:19 +08:00
feat: support doc heading (#4875)
Co-authored-by: GitHub Actions <actions@github.com>
This commit is contained in:
co-authored by
GitHub Actions
parent
060afe5759
commit
b605b83030
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
@@ -99,18 +99,6 @@ export const DEFAULT_DOCUMENT_DATA_CN: IDocumentData = {
|
||||
bl: BooleanNumber.TRUE,
|
||||
},
|
||||
},
|
||||
{
|
||||
st: 14,
|
||||
ed: 3064,
|
||||
ts: {
|
||||
fs: 12,
|
||||
ff: 'Microsoft YaHei',
|
||||
cl: {
|
||||
rgb: 'rgb(30, 30, 30)',
|
||||
},
|
||||
bl: BooleanNumber.FALSE,
|
||||
},
|
||||
},
|
||||
],
|
||||
paragraphs: [
|
||||
{
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
import { addCustomDecorationTextX, deleteCustomDecorationTextX } from './custom-decoration';
|
||||
import { copyCustomRange, getCustomRangesInterestsWithSelection, isIntersecting } from './custom-range';
|
||||
import { addDrawing } from './drawings';
|
||||
import { changeParagraphBulletNestLevel, setParagraphBullet, switchParagraphBullet, toggleChecklistParagraph } from './paragraph';
|
||||
import { changeParagraphBulletNestLevel, setParagraphBullet, setParagraphStyle, switchParagraphBullet, toggleChecklistParagraph } from './paragraph';
|
||||
import { fromPlainText, getPlainText, isEmptyDocument } from './parse';
|
||||
import { isSegmentIntersects, makeSelection, normalizeSelection } from './selection';
|
||||
import { getParagraphsInRange, getParagraphsInRanges, isSegmentIntersects, makeSelection, normalizeSelection } from './selection';
|
||||
import { addCustomRangeTextX, deleteCustomRangeTextX, deleteSelectionTextX, replaceSelectionTextRuns, replaceSelectionTextX, retainSelectionTextX } from './text-x-utils';
|
||||
|
||||
export class BuildTextUtils {
|
||||
@@ -47,6 +47,8 @@ export class BuildTextUtils {
|
||||
|
||||
static range = {
|
||||
isIntersects: isSegmentIntersects,
|
||||
getParagraphsInRange,
|
||||
getParagraphsInRanges,
|
||||
};
|
||||
|
||||
static transform = {
|
||||
@@ -62,6 +64,9 @@ export class BuildTextUtils {
|
||||
toggleChecklist: toggleChecklistParagraph,
|
||||
changeNestLevel: changeParagraphBulletNestLevel,
|
||||
},
|
||||
style: {
|
||||
set: setParagraphStyle,
|
||||
},
|
||||
};
|
||||
|
||||
static drawing = {
|
||||
|
||||
@@ -14,13 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { ICustomTable, IParagraph } from '../../../../types/interfaces';
|
||||
import type { ITextRange } from '../../../../sheets/typedef';
|
||||
import type { ICustomTable, IParagraph, IParagraphStyle, ITextStyle } from '../../../../types/interfaces';
|
||||
import type { DocumentDataModel } from '../../document-data-model';
|
||||
import { MemoryCursor } from '../../../../common/memory-cursor';
|
||||
import { Tools, UpdateDocsAttributeType } from '../../../../shared';
|
||||
import { PRESET_LIST_TYPE, PresetListType } from '../../preset-list-type';
|
||||
import { TextXActionType } from '../action-types';
|
||||
import { TextX } from '../text-x';
|
||||
import { getParagraphsInRanges } from './selection';
|
||||
|
||||
export interface ISwitchParagraphBulletParams {
|
||||
paragraphs: IParagraph[];
|
||||
@@ -241,7 +243,7 @@ export function hasParagraphInTable(paragraph: IParagraph, tables: ICustomTable[
|
||||
}
|
||||
|
||||
export const changeParagraphBulletNestLevel = (params: IChangeParagraphBulletNestLevelParams) => {
|
||||
const { paragraphs: currentParagraphs, segmentId, document: docDataModel, type } = params;
|
||||
const { paragraphs: currentParagraphs, document: docDataModel, type } = params;
|
||||
const memoryCursor = new MemoryCursor();
|
||||
|
||||
memoryCursor.reset();
|
||||
@@ -305,3 +307,73 @@ export const changeParagraphBulletNestLevel = (params: IChangeParagraphBulletNes
|
||||
|
||||
return textX;
|
||||
};
|
||||
|
||||
interface ISetParagraphStyleParams {
|
||||
textRanges: readonly ITextRange[];
|
||||
segmentId?: string;
|
||||
document: DocumentDataModel;
|
||||
style: IParagraphStyle;
|
||||
paragraphTextRun?: ITextStyle;
|
||||
}
|
||||
|
||||
export const setParagraphStyle = (params: ISetParagraphStyleParams) => {
|
||||
const { textRanges, segmentId, document: docDataModel, style, paragraphTextRun } = params;
|
||||
const paragraphs = docDataModel.getSelfOrHeaderFooterModel(segmentId).getBody()?.paragraphs ?? [];
|
||||
const currentParagraphs = getParagraphsInRanges(textRanges, paragraphs);
|
||||
const memoryCursor = new MemoryCursor();
|
||||
const textX = new TextX();
|
||||
currentParagraphs.sort((a, b) => a.startIndex - b.startIndex);
|
||||
const start = Math.max(0, currentParagraphs[0].paragraphStart - 1);
|
||||
|
||||
if (start > 0) {
|
||||
textX.push({
|
||||
t: TextXActionType.RETAIN,
|
||||
len: start - memoryCursor.cursor,
|
||||
});
|
||||
memoryCursor.moveCursorTo(start);
|
||||
}
|
||||
|
||||
for (const paragraph of currentParagraphs) {
|
||||
const { startIndex, paragraphStyle = {} } = paragraph;
|
||||
const len = startIndex - memoryCursor.cursor;
|
||||
textX.push({
|
||||
t: TextXActionType.RETAIN,
|
||||
len,
|
||||
...paragraphTextRun
|
||||
? {
|
||||
body: {
|
||||
dataStream: '',
|
||||
textRuns: [{
|
||||
ts: paragraphTextRun,
|
||||
st: 0,
|
||||
ed: len,
|
||||
}],
|
||||
},
|
||||
coverType: UpdateDocsAttributeType.REPLACE,
|
||||
}
|
||||
: null,
|
||||
});
|
||||
|
||||
textX.push({
|
||||
t: TextXActionType.RETAIN,
|
||||
len: 1,
|
||||
body: {
|
||||
dataStream: '',
|
||||
paragraphs: [
|
||||
{
|
||||
startIndex: 0,
|
||||
paragraphStyle: {
|
||||
...paragraphStyle,
|
||||
...style,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
coverType: UpdateDocsAttributeType.REPLACE,
|
||||
});
|
||||
|
||||
memoryCursor.moveCursorTo(startIndex + 1);
|
||||
}
|
||||
|
||||
return textX;
|
||||
};
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Nullable } from '../../../../shared';
|
||||
import type { ITextRange } from '../../../../sheets/typedef';
|
||||
import type { IParagraph, IParagraphRange } from '../../../../types/interfaces';
|
||||
|
||||
export function makeSelection(startOffset: number, endOffset?: number): ITextRange {
|
||||
if (typeof endOffset === 'undefined') {
|
||||
@@ -43,3 +45,46 @@ export function normalizeSelection(selection: ITextRange): ITextRange {
|
||||
export function isSegmentIntersects(start: number, end: number, start2: number, end2: number) {
|
||||
return Math.max(start, start2) <= Math.min(end, end2);
|
||||
}
|
||||
|
||||
export function getParagraphsInRange(activeRange: ITextRange, paragraphs: IParagraph[]) {
|
||||
const { startOffset, endOffset } = activeRange;
|
||||
const results: IParagraphRange[] = [];
|
||||
|
||||
let start = -1;
|
||||
|
||||
for (let i = 0; i < paragraphs.length; i++) {
|
||||
const paragraph = paragraphs[i];
|
||||
const prevParagraph: Nullable<IParagraph> = paragraphs[i - 1];
|
||||
const { startIndex } = paragraph;
|
||||
|
||||
if ((startOffset > start && startOffset <= startIndex) || (endOffset > start && endOffset <= startIndex)) {
|
||||
results.push({
|
||||
...paragraph,
|
||||
paragraphStart: (prevParagraph?.startIndex ?? -1) + 1,
|
||||
paragraphEnd: paragraph.startIndex,
|
||||
});
|
||||
} else if (startIndex >= startOffset && startIndex <= endOffset) {
|
||||
results.push({
|
||||
...paragraph,
|
||||
paragraphStart: (prevParagraph?.startIndex ?? -1) + 1,
|
||||
paragraphEnd: paragraph.startIndex,
|
||||
});
|
||||
}
|
||||
|
||||
start = startIndex;
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
export function getParagraphsInRanges(ranges: readonly ITextRange[], paragraphs: IParagraph[]) {
|
||||
const results: IParagraphRange[] = [];
|
||||
|
||||
for (const range of ranges) {
|
||||
const ps = getParagraphsInRange(range, paragraphs);
|
||||
|
||||
results.push(...ps);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Nullable } from '../../shared';
|
||||
import type { ITextStyle } from '../interfaces';
|
||||
import { DOCS_FORMULA_BAR_EDITOR_UNIT_ID_KEY, DOCS_NORMAL_EDITOR_UNIT_ID_KEY, DOCS_ZEN_EDITOR_UNIT_ID_KEY } from '../../common/const';
|
||||
import {
|
||||
BooleanNumber,
|
||||
@@ -22,6 +24,7 @@ import {
|
||||
VerticalAlign,
|
||||
WrapStrategy,
|
||||
} from '../enum';
|
||||
import { NamedStyleType } from '../interfaces';
|
||||
|
||||
/**
|
||||
* Used as an illegal range array return value
|
||||
@@ -175,3 +178,16 @@ export const DEFAULT_SLIDE = {
|
||||
};
|
||||
|
||||
export const SHEET_EDITOR_UNITS = [DOCS_NORMAL_EDITOR_UNIT_ID_KEY, DOCS_ZEN_EDITOR_UNIT_ID_KEY, DOCS_FORMULA_BAR_EDITOR_UNIT_ID_KEY];
|
||||
|
||||
export const NAMED_STYLE_MAP: Record<NamedStyleType, Nullable<ITextStyle>> = {
|
||||
[NamedStyleType.HEADING_1]: { fs: 20, bl: 1 }, // Heading 1: 20pt, bold
|
||||
[NamedStyleType.HEADING_2]: { fs: 18, bl: 1 }, // Heading 2: 18pt, bold
|
||||
[NamedStyleType.HEADING_3]: { fs: 16, bl: 1 }, // Heading 3: 16pt, bold
|
||||
[NamedStyleType.HEADING_4]: { fs: 14, bl: 1 }, // Heading 4: 14pt, bold
|
||||
[NamedStyleType.HEADING_5]: { fs: 12, bl: 1 }, // Heading 5: 12pt, bold
|
||||
[NamedStyleType.HEADING_6]: { fs: 11, bl: 1 }, // Heading 6: 11pt, bold
|
||||
[NamedStyleType.NORMAL_TEXT]: { fs: 11 }, // Normal text: 11pt
|
||||
[NamedStyleType.TITLE]: { fs: 26, bl: 1 }, // Title: 26pt, bold
|
||||
[NamedStyleType.SUBTITLE]: { fs: 15, cl: { rgb: '#999999' } }, // Subtitle: 15pt
|
||||
[NamedStyleType.NAMED_STYLE_TYPE_UNSPECIFIED]: null,
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ export function getTextRunAtPosition(
|
||||
const retTextRun: ITextRun = {
|
||||
st: 0,
|
||||
ed: 0,
|
||||
ts: isCellEditor ? {} : defaultStyle,
|
||||
ts: {},
|
||||
};
|
||||
|
||||
if (isFormula) {
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
import type { DocumentDataModel, IAccessor, ICommand, IMutationInfo, IParagraphStyle } from '@univerjs/core';
|
||||
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
|
||||
import { CommandType, ICommandService, IUniverInstanceService, JSONX, MemoryCursor, TextX, TextXActionType, UniverInstanceType, UpdateDocsAttributeType } from '@univerjs/core';
|
||||
import { BuildTextUtils, CommandType, ICommandService, IUniverInstanceService, JSONX, MemoryCursor, TextX, TextXActionType, UniverInstanceType, UpdateDocsAttributeType } from '@univerjs/core';
|
||||
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
|
||||
import { getRichTextEditPath } from '../util';
|
||||
import { getParagraphsInRanges } from './list.command';
|
||||
|
||||
export interface IDocParagraphSettingCommandParams {
|
||||
paragraph: Partial<Pick<IParagraphStyle, 'hanging' | 'horizontalAlign' | 'spaceBelow' | 'spaceAbove' | 'indentEnd' | 'indentStart' | 'lineSpacing' | 'indentFirstLine' | 'snapToGrid' | 'spacingRule'>>;
|
||||
@@ -46,7 +45,7 @@ export const DocParagraphSettingCommand: ICommand<IDocParagraphSettingCommandPar
|
||||
const unitId = docDataModel.getUnitId();
|
||||
|
||||
const allParagraphs = docDataModel.getSelfOrHeaderFooterModel(segmentId).getBody()?.paragraphs ?? [];
|
||||
const paragraphs = getParagraphsInRanges(docRanges, allParagraphs) ?? [];
|
||||
const paragraphs = BuildTextUtils.range.getParagraphsInRanges(docRanges, allParagraphs) ?? [];
|
||||
|
||||
const doMutation: IMutationInfo<IRichTextEditingMutationParams> = {
|
||||
id: RichTextEditingMutation.id,
|
||||
|
||||
@@ -67,7 +67,7 @@ export const ListOperationCommand: ICommand<IListOperationCommandParams> = {
|
||||
return false;
|
||||
}
|
||||
|
||||
const currentParagraphs = getParagraphsInRanges(docRanges, paragraphs);
|
||||
const currentParagraphs = BuildTextUtils.range.getParagraphsInRanges(docRanges, paragraphs);
|
||||
|
||||
const unitId = docDataModel.getUnitId();
|
||||
|
||||
@@ -129,7 +129,7 @@ export const ChangeListTypeCommand: ICommand<IChangeListTypeCommandParams> = {
|
||||
return false;
|
||||
}
|
||||
|
||||
const currentParagraphs = getParagraphsInRanges(selections, paragraphs);
|
||||
const currentParagraphs = BuildTextUtils.range.getParagraphsInRanges(selections, paragraphs);
|
||||
|
||||
const unitId = docDataModel.getUnitId();
|
||||
const textX = BuildTextUtils.paragraph.bullet.set({
|
||||
@@ -199,7 +199,7 @@ export const ChangeListNestingLevelCommand: ICommand<IChangeListNestingLevelComm
|
||||
return false;
|
||||
}
|
||||
|
||||
const currentParagraphs = getParagraphsInRange(activeRange, paragraphs);
|
||||
const currentParagraphs = BuildTextUtils.range.getParagraphsInRange(activeRange, paragraphs);
|
||||
|
||||
const unitId = docDataModel.getUnitId();
|
||||
const jsonX = JSONX.getInstance();
|
||||
@@ -472,29 +472,8 @@ export const QuickListCommand: ICommand<IQuickListCommandParams> = {
|
||||
},
|
||||
};
|
||||
|
||||
export function getParagraphsInRange(activeRange: ITextRangeWithStyle, paragraphs: IParagraph[]) {
|
||||
const { startOffset, endOffset } = activeRange;
|
||||
const results: IParagraph[] = [];
|
||||
|
||||
let start = -1;
|
||||
|
||||
for (const paragraph of paragraphs) {
|
||||
const { startIndex } = paragraph;
|
||||
|
||||
if ((startOffset > start && startOffset <= startIndex) || (endOffset > start && endOffset <= startIndex)) {
|
||||
results.push(paragraph);
|
||||
} else if (startIndex >= startOffset && startIndex <= endOffset) {
|
||||
results.push(paragraph);
|
||||
}
|
||||
|
||||
start = startIndex;
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
export function getParagraphsRelative(ranges: ITextRangeWithStyle[], paragraphs: IParagraph[]) {
|
||||
const selectionParagraphs = getParagraphsInRanges(ranges, paragraphs);
|
||||
const selectionParagraphs: IParagraph[] = BuildTextUtils.range.getParagraphsInRanges(ranges, paragraphs);
|
||||
const startIndex = paragraphs.indexOf(selectionParagraphs[0]);
|
||||
const endIndex = paragraphs.indexOf(selectionParagraphs[selectionParagraphs.length - 1]);
|
||||
if (selectionParagraphs[0].bullet) {
|
||||
@@ -519,18 +498,6 @@ export function getParagraphsRelative(ranges: ITextRangeWithStyle[], paragraphs:
|
||||
return selectionParagraphs;
|
||||
}
|
||||
|
||||
export function getParagraphsInRanges(ranges: ITextRangeWithStyle[], paragraphs: IParagraph[]) {
|
||||
const results: IParagraph[] = [];
|
||||
|
||||
for (const range of ranges) {
|
||||
const ps = getParagraphsInRange(range, paragraphs);
|
||||
|
||||
results.push(...ps);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
export function findNearestSectionBreak(currentIndex: number, sectionBreaks: ISectionBreak[]) {
|
||||
const sortedSectionBreaks = sectionBreaks.sort(sortRulesFactory('startIndex'));
|
||||
for (let i = 0; i < sortedSectionBreaks.length; i++) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import type { ICommand, IMutationInfo, IParagraphStyle } from '@univerjs/core';
|
||||
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
|
||||
|
||||
import {
|
||||
BuildTextUtils,
|
||||
CommandType,
|
||||
HorizontalAlign,
|
||||
ICommandService,
|
||||
@@ -30,7 +31,6 @@ import {
|
||||
} from '@univerjs/core';
|
||||
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
|
||||
import { getRichTextEditPath } from '../util';
|
||||
import { getParagraphsInRanges } from './list.command';
|
||||
|
||||
interface IAlignOperationCommandParams {
|
||||
alignType: HorizontalAlign;
|
||||
@@ -67,7 +67,7 @@ export const AlignOperationCommand: ICommand<IAlignOperationCommandParams> = {
|
||||
return false;
|
||||
}
|
||||
|
||||
const currentParagraphs = getParagraphsInRanges(allRanges, paragraphs);
|
||||
const currentParagraphs = BuildTextUtils.range.getParagraphsInRanges(allRanges, paragraphs);
|
||||
|
||||
const unitId = docDataModel.getUnitId();
|
||||
const isAlreadyAligned = currentParagraphs.every((paragraph) => paragraph.paragraphStyle?.horizontalAlign === alignType);
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { DocumentDataModel, ICommand, IMutationInfo } from '@univerjs/core';
|
||||
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
|
||||
import { BuildTextUtils, CommandType, generateRandomId, ICommandService, IUniverInstanceService, JSONX, NamedStyleType, UniverInstanceType } from '@univerjs/core';
|
||||
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
|
||||
import { getRichTextEditPath } from '../util';
|
||||
|
||||
export interface ISetParagraphNamedStyleCommandParams {
|
||||
value: NamedStyleType;
|
||||
}
|
||||
|
||||
export const SetParagraphNamedStyleCommand: ICommand<ISetParagraphNamedStyleCommandParams> = {
|
||||
id: 'doc.command.set-paragraph-named-style',
|
||||
type: CommandType.COMMAND,
|
||||
handler(accessor, params) {
|
||||
if (!params) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const univerInstanceService = accessor.get(IUniverInstanceService);
|
||||
const documentDataModel = univerInstanceService.getCurrentUnitOfType<DocumentDataModel>(UniverInstanceType.UNIVER_DOC);
|
||||
if (!documentDataModel) {
|
||||
return false;
|
||||
}
|
||||
const unitId = documentDataModel.getUnitId();
|
||||
const selectionService = accessor.get(DocSelectionManagerService);
|
||||
const selections = selectionService.getTextRanges({ unitId, subUnitId: unitId })?.filter((i) => !i.segmentId);
|
||||
if (!selections?.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const textX = BuildTextUtils.paragraph.style.set({
|
||||
document: documentDataModel,
|
||||
textRanges: selections,
|
||||
style: {
|
||||
namedStyleType: params.value,
|
||||
headingId: !params.value || params.value === NamedStyleType.NORMAL_TEXT ? undefined : generateRandomId(6),
|
||||
},
|
||||
paragraphTextRun: {},
|
||||
|
||||
});
|
||||
|
||||
const doMutation: IMutationInfo<IRichTextEditingMutationParams> = {
|
||||
id: RichTextEditingMutation.id,
|
||||
params: {
|
||||
actions: [],
|
||||
textRanges: selections,
|
||||
unitId,
|
||||
},
|
||||
};
|
||||
|
||||
const jsonX = JSONX.getInstance();
|
||||
const path = getRichTextEditPath(documentDataModel);
|
||||
doMutation.params.actions = jsonX.editOp(textX.serialize(), path);
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const result = commandService.syncExecuteCommand(doMutation.id, doMutation.params);
|
||||
return Boolean(result);
|
||||
},
|
||||
};
|
||||
@@ -24,6 +24,7 @@ import { ResetInlineFormatTextBackgroundColorCommand, SetInlineFormatBoldCommand
|
||||
|
||||
import { BulletListCommand, CheckListCommand, OrderListCommand } from '../commands/commands/list.command';
|
||||
import { AlignCenterCommand, AlignJustifyCommand, AlignLeftCommand, AlignRightCommand } from '../commands/commands/paragraph-align.command';
|
||||
import { SetParagraphNamedStyleCommand } from '../commands/commands/set-heading.command';
|
||||
import { SwitchDocModeCommand } from '../commands/commands/switch-doc-mode.command';
|
||||
import { DocTableDeleteColumnsCommand, DocTableDeleteRowsCommand, DocTableDeleteTableCommand } from '../commands/commands/table/doc-table-delete.command';
|
||||
import { DocTableInsertColumnLeftCommand, DocTableInsertColumnRightCommand, DocTableInsertRowAboveCommand, DocTableInsertRowBellowCommand } from '../commands/commands/table/doc-table-insert.command';
|
||||
@@ -60,6 +61,7 @@ import {
|
||||
FontFamilySelectorMenuItemFactory,
|
||||
FontSizeSelectorMenuItemFactory,
|
||||
HeaderFooterMenuItemFactory,
|
||||
HeadingSelectorMenuItemFactory,
|
||||
HorizontalLineFactory,
|
||||
InsertTableMenuFactory,
|
||||
ItalicMenuItemFactory,
|
||||
@@ -100,6 +102,10 @@ export const menuSchema: MenuSchemaType = {
|
||||
order: 5,
|
||||
menuItemFactory: SuperscriptMenuItemFactory,
|
||||
},
|
||||
[SetParagraphNamedStyleCommand.id]: {
|
||||
order: 5.5,
|
||||
menuItemFactory: HeadingSelectorMenuItemFactory,
|
||||
},
|
||||
[SetInlineFormatFontSizeCommand.id]: {
|
||||
order: 6,
|
||||
menuItemFactory: FontSizeSelectorMenuItemFactory,
|
||||
|
||||
@@ -21,12 +21,15 @@ import type { Subscription } from 'rxjs';
|
||||
import {
|
||||
BaselineOffset,
|
||||
BooleanNumber,
|
||||
BuildTextUtils,
|
||||
DEFAULT_STYLES,
|
||||
DOCS_ZEN_EDITOR_UNIT_ID_KEY,
|
||||
DocumentFlavor,
|
||||
HorizontalAlign,
|
||||
ICommandService,
|
||||
IUniverInstanceService,
|
||||
NAMED_STYLE_MAP,
|
||||
NamedStyleType,
|
||||
ThemeService,
|
||||
UniverInstanceType,
|
||||
} from '@univerjs/core';
|
||||
@@ -38,9 +41,12 @@ import {
|
||||
} from '@univerjs/docs';
|
||||
import { DocumentEditArea, IRenderManagerService } from '@univerjs/engine-render';
|
||||
import {
|
||||
COMMON_LABEL_COMPONENT,
|
||||
FONT_FAMILY_LIST,
|
||||
FONT_SIZE_LIST,
|
||||
getMenuHiddenObservable,
|
||||
HEADING_ITEM_COMPONENT,
|
||||
HEADING_LIST,
|
||||
MenuItemType,
|
||||
} from '@univerjs/ui';
|
||||
|
||||
@@ -48,8 +54,9 @@ import { combineLatest, map, Observable } from 'rxjs';
|
||||
import { OpenHeaderFooterPanelCommand } from '../../commands/commands/doc-header-footer.command';
|
||||
import { HorizontalLineCommand } from '../../commands/commands/doc-horizontal-line.command';
|
||||
import { getStyleInTextRange, ResetInlineFormatTextBackgroundColorCommand, SetInlineFormatBoldCommand, SetInlineFormatCommand, SetInlineFormatFontFamilyCommand, SetInlineFormatFontSizeCommand, SetInlineFormatItalicCommand, SetInlineFormatStrikethroughCommand, SetInlineFormatSubscriptCommand, SetInlineFormatSuperscriptCommand, SetInlineFormatTextBackgroundColorCommand, SetInlineFormatTextColorCommand, SetInlineFormatUnderlineCommand } from '../../commands/commands/inline-format.command';
|
||||
import { BulletListCommand, CheckListCommand, getParagraphsInRange, OrderListCommand } from '../../commands/commands/list.command';
|
||||
import { BulletListCommand, CheckListCommand, OrderListCommand } from '../../commands/commands/list.command';
|
||||
import { AlignCenterCommand, AlignJustifyCommand, AlignLeftCommand, AlignOperationCommand, AlignRightCommand } from '../../commands/commands/paragraph-align.command';
|
||||
import { SetParagraphNamedStyleCommand } from '../../commands/commands/set-heading.command';
|
||||
import { SwitchDocModeCommand } from '../../commands/commands/switch-doc-mode.command';
|
||||
import { DocCreateTableOperation } from '../../commands/operations/doc-create-table.operation';
|
||||
import { getCommandSkeleton } from '../../commands/util';
|
||||
@@ -530,6 +537,55 @@ export function FontSizeSelectorMenuItemFactory(accessor: IAccessor): IMenuSelec
|
||||
};
|
||||
}
|
||||
|
||||
export function HeadingSelectorMenuItemFactory(accessor: IAccessor): IMenuSelectorItem<number> {
|
||||
const commandService = accessor.get(ICommandService);
|
||||
|
||||
return {
|
||||
id: SetParagraphNamedStyleCommand.id,
|
||||
type: MenuItemType.SELECTOR,
|
||||
tooltip: 'toolbar.heading.tooltip',
|
||||
label: {
|
||||
name: COMMON_LABEL_COMPONENT,
|
||||
props: {
|
||||
selections: HEADING_LIST,
|
||||
},
|
||||
},
|
||||
selections: HEADING_LIST.map((item) => ({
|
||||
label: {
|
||||
name: HEADING_ITEM_COMPONENT,
|
||||
props: {
|
||||
value: item.value,
|
||||
text: item.label,
|
||||
},
|
||||
},
|
||||
value: item.value,
|
||||
})),
|
||||
value$: new Observable((subscriber) => {
|
||||
const DEFAULT_TYPE = NamedStyleType.NORMAL_TEXT;
|
||||
const disposable = commandService.onCommandExecuted((c) => {
|
||||
const id = c.id;
|
||||
|
||||
if (id === SetTextSelectionsOperation.id || id === SetInlineFormatFontSizeCommand.id) {
|
||||
const paragraph = getParagraphStyleAtCursor(accessor);
|
||||
if (paragraph == null) {
|
||||
subscriber.next(DEFAULT_TYPE);
|
||||
return;
|
||||
}
|
||||
|
||||
const namedStyleType = paragraph.paragraphStyle?.namedStyleType ?? DEFAULT_TYPE;
|
||||
subscriber.next(namedStyleType);
|
||||
}
|
||||
});
|
||||
|
||||
subscriber.next(DEFAULT_TYPE);
|
||||
|
||||
return disposable.dispose;
|
||||
}),
|
||||
disabled$: disableMenuWhenNoDocRange(accessor),
|
||||
hidden$: getMenuHiddenObservable(accessor, UniverInstanceType.UNIVER_DOC),
|
||||
};
|
||||
}
|
||||
|
||||
export function TextColorSelectorMenuItemFactory(accessor: IAccessor): IMenuSelectorItem<string> {
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const themeService = accessor.get(ThemeService);
|
||||
@@ -774,7 +830,7 @@ const listValueFactory$ = (accessor: IAccessor) => {
|
||||
|
||||
if (range) {
|
||||
const doc = docDataModel.getSelfOrHeaderFooterModel(range?.segmentId);
|
||||
const paragraphs = getParagraphsInRange(range, doc.getBody()?.paragraphs ?? []);
|
||||
const paragraphs = BuildTextUtils.range.getParagraphsInRange(range, doc.getBody()?.paragraphs ?? []);
|
||||
let listType: string | undefined;
|
||||
if (paragraphs.every((p) => {
|
||||
if (!listType) {
|
||||
@@ -939,11 +995,13 @@ function getFontStyleAtCursor(accessor: IAccessor) {
|
||||
|
||||
const defaultTextStyle = docMenuStyleService.getDefaultStyle();
|
||||
const cacheStyle = docMenuStyleService.getStyleCache() ?? {};
|
||||
|
||||
const paragraph = getParagraphStyleAtCursor(accessor);
|
||||
const namedStyle = paragraph?.paragraphStyle?.namedStyleType ? NAMED_STYLE_MAP[paragraph?.paragraphStyle?.namedStyleType] : null;
|
||||
if (docDataModel == null || activeRange == null) {
|
||||
return {
|
||||
ts: {
|
||||
...defaultTextStyle,
|
||||
...namedStyle,
|
||||
...cacheStyle,
|
||||
},
|
||||
};
|
||||
@@ -956,6 +1014,7 @@ function getFontStyleAtCursor(accessor: IAccessor) {
|
||||
return {
|
||||
ts: {
|
||||
...defaultTextStyle,
|
||||
...namedStyle,
|
||||
...cacheStyle,
|
||||
},
|
||||
};
|
||||
@@ -966,6 +1025,7 @@ function getFontStyleAtCursor(accessor: IAccessor) {
|
||||
return {
|
||||
ts: {
|
||||
...curTextStyle,
|
||||
...namedStyle,
|
||||
...cacheStyle,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -73,6 +73,7 @@ import {
|
||||
import { AlignCenterCommand, AlignJustifyCommand, AlignLeftCommand, AlignOperationCommand, AlignRightCommand } from './commands/commands/paragraph-align.command';
|
||||
import { CoverContentCommand, ReplaceContentCommand, ReplaceSelectionCommand, ReplaceSnapshotCommand, ReplaceTextRunsCommand } from './commands/commands/replace-content.command';
|
||||
import { SetDocZoomRatioCommand } from './commands/commands/set-doc-zoom-ratio.command';
|
||||
import { SetParagraphNamedStyleCommand } from './commands/commands/set-heading.command';
|
||||
import { SwitchDocModeCommand } from './commands/commands/switch-doc-mode.command';
|
||||
import { CreateDocTableCommand } from './commands/commands/table/doc-table-create.command';
|
||||
import { DocTableDeleteColumnsCommand, DocTableDeleteRowsCommand, DocTableDeleteTableCommand } from './commands/commands/table/doc-table-delete.command';
|
||||
@@ -262,8 +263,9 @@ export class UniverDocsUIPlugin extends Plugin {
|
||||
ReplaceTextRunsCommand,
|
||||
ReplaceSelectionCommand,
|
||||
InsertCustomRangeCommand,
|
||||
SetParagraphNamedStyleCommand,
|
||||
].forEach((e) => {
|
||||
this._commandService.registerCommand(e);
|
||||
this.disposeWithMe(this._commandService.registerCommand(e));
|
||||
});
|
||||
|
||||
[DocCopyCommand, DocCutCommand, DocPasteCommand].forEach((command) => this.disposeWithMe(this._commandService.registerMultipleCommand(command)));
|
||||
|
||||
@@ -95,7 +95,6 @@ export {
|
||||
SetInlineFormatTextColorCommand,
|
||||
SetInlineFormatUnderlineCommand,
|
||||
} from './commands/commands/inline-format.command';
|
||||
export { getParagraphsInRange, getParagraphsInRanges } from './commands/commands/list.command';
|
||||
export {
|
||||
BulletListCommand,
|
||||
ChangeListNestingLevelCommand,
|
||||
@@ -150,5 +149,5 @@ export { type IMoveCursorOperationParams, MoveSelectionOperation } from './comma
|
||||
export { MoveCursorOperation } from './commands/operations/doc-cursor.operation';
|
||||
export { DocSelectAllCommand } from './commands/commands/doc-select-all.command';
|
||||
export { type ISetDocZoomRatioOperationParams, SetDocZoomRatioOperation } from './commands/operations/set-doc-zoom-ratio.operation';
|
||||
|
||||
export { SetParagraphNamedStyleCommand } from './commands/commands/set-heading.command';
|
||||
// #endregion
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import type { DocumentDataModel, IParagraph, ISectionBreak } from '@univerjs/core';
|
||||
import type { IDocParagraphSettingCommandParams } from '../../../commands/commands/doc-paragraph-setting.command';
|
||||
import { ICommandService, IUniverInstanceService, SpacingRule, UniverInstanceType } from '@univerjs/core';
|
||||
import { BuildTextUtils, ICommandService, IUniverInstanceService, SpacingRule, UniverInstanceType } from '@univerjs/core';
|
||||
import { DocSelectionManagerService, DocSkeletonManagerService } from '@univerjs/docs';
|
||||
import { getNumberUnitValue, IRenderManagerService } from '@univerjs/engine-render';
|
||||
import { useDependency } from '@univerjs/ui';
|
||||
@@ -24,7 +24,7 @@ import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { bufferTime, filter, map } from 'rxjs/operators';
|
||||
import { DocParagraphSettingCommand } from '../../../commands/commands/doc-paragraph-setting.command';
|
||||
import { findNearestSectionBreak, getParagraphsInRanges } from '../../../commands/commands/list.command';
|
||||
import { findNearestSectionBreak } from '../../../commands/commands/list.command';
|
||||
import { DocParagraphSettingController } from '../../../controllers/doc-paragraph-setting.controller';
|
||||
|
||||
const useDocRanges = () => {
|
||||
@@ -59,7 +59,7 @@ export const useCurrentParagraph = () => {
|
||||
const segmentId = docRanges[0].segmentId;
|
||||
|
||||
const paragraphs = docDataModel.getSelfOrHeaderFooterModel(segmentId).getBody()?.paragraphs ?? [];
|
||||
const currentParagraphs = getParagraphsInRanges(docRanges, paragraphs) ?? [];
|
||||
const currentParagraphs = BuildTextUtils.range.getParagraphsInRanges(docRanges, paragraphs) ?? [];
|
||||
|
||||
return currentParagraphs;
|
||||
};
|
||||
|
||||
@@ -38,8 +38,8 @@ import type {
|
||||
IDocumentSkeletonSection,
|
||||
ISkeletonResourceReference,
|
||||
} from '../../../basics/i-document-skeleton-cached';
|
||||
|
||||
import type { IDocsConfig, IParagraphConfig, ISectionBreakConfig } from '../../../basics/interfaces';
|
||||
|
||||
import type { DataStreamTreeNode } from '../view-model/data-stream-tree-node';
|
||||
import type { DocumentViewModel } from '../view-model/document-view-model';
|
||||
import type { Hyphen } from './hyphenation/hyphen';
|
||||
@@ -54,6 +54,7 @@ import {
|
||||
GridType,
|
||||
HorizontalAlign,
|
||||
mergeWith,
|
||||
NAMED_STYLE_MAP,
|
||||
NumberUnitType,
|
||||
ObjectMatrix,
|
||||
ObjectRelativeFromH,
|
||||
@@ -851,7 +852,7 @@ export function getFontCreateConfig(
|
||||
const customRange = viewModel.getCustomRange(index + startIndex);
|
||||
const showCustomRange = customRange && (customRange.show !== false);
|
||||
const customRangeStyle = showCustomRange ? getCustomRangeStyle(customRange) : null;
|
||||
const hasAddonStyle = showCustomRange || showCustomDecoration || !!bullet;
|
||||
const hasAddonStyle = showCustomRange || showCustomDecoration || !!bullet || paragraphStyle?.namedStyleType;
|
||||
const { st, ed } = textRun;
|
||||
let { ts: textStyle = {} } = textRun;
|
||||
const cache = fontCreateConfigCache.getValue(st, ed);
|
||||
@@ -859,11 +860,14 @@ export function getFontCreateConfig(
|
||||
return cache;
|
||||
}
|
||||
|
||||
const { snapToGrid = BooleanNumber.TRUE } = paragraphStyle;
|
||||
const { snapToGrid = BooleanNumber.TRUE, namedStyleType } = paragraphStyle;
|
||||
const bulletTextStyle = bullet ? getBulletParagraphTextStyle(bullet, viewModel) : null;
|
||||
// Apply named style if it exists
|
||||
const namedStyle = namedStyleType ? NAMED_STYLE_MAP[namedStyleType] : null;
|
||||
|
||||
textStyle = {
|
||||
...documentTextStyle,
|
||||
...namedStyle,
|
||||
...textStyle,
|
||||
...customDecorationStyle,
|
||||
...customRangeStyle,
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { LocaleService } from '@univerjs/core';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { useDependency } from '../../utils/di';
|
||||
|
||||
export interface ICommonLabelProps {
|
||||
value: string | number;
|
||||
selections: { value: string | number; label: string }[];
|
||||
}
|
||||
|
||||
export const CommonLabel = (props: ICommonLabelProps) => {
|
||||
const { value, selections } = props;
|
||||
|
||||
const localeService = useDependency(LocaleService);
|
||||
|
||||
const viewValue = useMemo(() => {
|
||||
if (value == null) return '';
|
||||
return localeService.t(selections.find((item) => item.value === value)?.label ?? '');
|
||||
}, [value, selections]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="univer-overflow-hidden univer-truncate univer-text-[13px]"
|
||||
>
|
||||
{viewValue}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const COMMON_LABEL_COMPONENT = 'UI_PLUGIN_COMMON_LABEL_COMPONENT';
|
||||
@@ -15,4 +15,4 @@
|
||||
*/
|
||||
|
||||
export { FontSize } from './FontSize';
|
||||
export { FONT_SIZE_LIST } from './interface';
|
||||
export { FONT_SIZE_LIST, HEADING_LIST } from './interface';
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { ICustomComponentProps } from '../../services/menu/menu';
|
||||
import { NamedStyleType } from '@univerjs/core';
|
||||
|
||||
export interface IFontSizeProps extends ICustomComponentProps<string> {
|
||||
value: string;
|
||||
@@ -92,3 +93,42 @@ export const FONT_SIZE_LIST = [
|
||||
value: 72,
|
||||
},
|
||||
];
|
||||
|
||||
export const HEADING_LIST = [
|
||||
{
|
||||
label: 'toolbar.heading.normal',
|
||||
value: NamedStyleType.NORMAL_TEXT,
|
||||
},
|
||||
{
|
||||
label: 'toolbar.heading.title',
|
||||
value: NamedStyleType.TITLE,
|
||||
},
|
||||
{
|
||||
label: 'toolbar.heading.subTitle',
|
||||
value: NamedStyleType.SUBTITLE,
|
||||
},
|
||||
{
|
||||
label: 'toolbar.heading.1',
|
||||
value: NamedStyleType.HEADING_1,
|
||||
},
|
||||
{
|
||||
label: 'toolbar.heading.2',
|
||||
value: NamedStyleType.HEADING_2,
|
||||
},
|
||||
{
|
||||
label: 'toolbar.heading.3',
|
||||
value: NamedStyleType.HEADING_3,
|
||||
},
|
||||
{
|
||||
label: 'toolbar.heading.4',
|
||||
value: NamedStyleType.HEADING_4,
|
||||
},
|
||||
{
|
||||
label: 'toolbar.heading.5',
|
||||
value: NamedStyleType.HEADING_5,
|
||||
},
|
||||
{
|
||||
label: 'toolbar.heading.6',
|
||||
value: NamedStyleType.HEADING_6,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { NamedStyleType } from '@univerjs/core';
|
||||
import { LocaleService, NAMED_STYLE_MAP } from '@univerjs/core';
|
||||
import { useDependency } from '../../utils/di';
|
||||
|
||||
export const HeadingItem = (props: { value: NamedStyleType; text: string }) => {
|
||||
const { value, text } = props;
|
||||
const style = NAMED_STYLE_MAP[value];
|
||||
|
||||
const localeService = useDependency(LocaleService);
|
||||
|
||||
return (
|
||||
<span
|
||||
className="univer-text-[13px]"
|
||||
style={{
|
||||
fontSize: style?.fs,
|
||||
fontWeight: style?.bl ? 'bold' : 'normal',
|
||||
color: style?.cl?.rgb ?? undefined,
|
||||
}}
|
||||
>
|
||||
{localeService.t(text)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export const HEADING_ITEM_COMPONENT = 'UI_COMPONENT_HEADING_ITEM';
|
||||
@@ -14,8 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './common-label';
|
||||
export * from './custom-label';
|
||||
export * from './font-family';
|
||||
export * from './font-size';
|
||||
export * from './heading-item';
|
||||
export { useScrollYOverContainer } from './hooks/layout';
|
||||
export { type ISliderProps, Slider } from './slider';
|
||||
|
||||
@@ -20,6 +20,9 @@ import type { IWorkbenchOptions } from './ui.controller';
|
||||
import { Inject, Injector, IUniverInstanceService, LifecycleService, toDisposable } from '@univerjs/core';
|
||||
import { render as createRoot, unmount } from '@univerjs/design';
|
||||
import { IRenderManagerService } from '@univerjs/engine-render';
|
||||
import { ComponentManager } from '../../common';
|
||||
import { HEADING_ITEM_COMPONENT, HeadingItem } from '../../components';
|
||||
import { COMMON_LABEL_COMPONENT, CommonLabel } from '../../components/common-label';
|
||||
import { ILayoutService } from '../../services/layout/layout.service';
|
||||
import { IMenuManagerService } from '../../services/menu/menu-manager.service';
|
||||
import { BuiltInUIPart, IUIPartsService } from '../../services/parts/parts.service';
|
||||
@@ -40,16 +43,33 @@ export class DesktopUIController extends SingleUnitUIController {
|
||||
@ILayoutService layoutService: ILayoutService,
|
||||
@IUniverInstanceService instanceService: IUniverInstanceService,
|
||||
@IMenuManagerService menuManagerService: IMenuManagerService,
|
||||
@IUIPartsService uiPartsService: IUIPartsService
|
||||
@IUIPartsService uiPartsService: IUIPartsService,
|
||||
@Inject(ComponentManager) private readonly _componentManager: ComponentManager
|
||||
) {
|
||||
super(injector, instanceService, layoutService, lifecycleService, renderManagerService);
|
||||
|
||||
menuManagerService.mergeMenu(menuSchema);
|
||||
|
||||
this._initBuiltinComponents(uiPartsService);
|
||||
this._registerComponents();
|
||||
this._bootstrapWorkbench();
|
||||
}
|
||||
|
||||
private _registerComponents() {
|
||||
this.disposeWithMe(
|
||||
this._componentManager.register(
|
||||
COMMON_LABEL_COMPONENT,
|
||||
CommonLabel
|
||||
)
|
||||
);
|
||||
this.disposeWithMe(
|
||||
this._componentManager.register(
|
||||
HEADING_ITEM_COMPONENT,
|
||||
HeadingItem
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
override bootstrap(callback: (contentElement: HTMLElement, containerElement: HTMLElement) => void): IDisposable {
|
||||
return bootstrap(this._injector, this._config, callback);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,20 @@
|
||||
import type zhCN from './zh-CN';
|
||||
|
||||
const locale: typeof zhCN = {
|
||||
toolbar: {
|
||||
heading: {
|
||||
normal: 'Normal',
|
||||
title: 'Title',
|
||||
subTitle: 'Sub Title',
|
||||
1: 'Heading 1',
|
||||
2: 'Heading 2',
|
||||
3: 'Heading 3',
|
||||
4: 'Heading 4',
|
||||
5: 'Heading 5',
|
||||
6: 'Heading 6',
|
||||
tooltip: 'Set Heading',
|
||||
},
|
||||
},
|
||||
ribbon: {
|
||||
start: 'Start',
|
||||
insert: 'Insert',
|
||||
|
||||
@@ -17,6 +17,20 @@
|
||||
import type zhCN from './zh-CN';
|
||||
|
||||
const locale: typeof zhCN = {
|
||||
toolbar: {
|
||||
heading: {
|
||||
normal: 'متن عادی',
|
||||
title: 'عنوان',
|
||||
subTitle: 'زیر عنوان',
|
||||
1: 'عنوان 1',
|
||||
2: 'عنوان 2',
|
||||
3: 'عنوان 3',
|
||||
4: 'عنوان 4',
|
||||
5: 'عنوان 5',
|
||||
6: 'عنوان 6',
|
||||
tooltip: 'تنظیم عنوان',
|
||||
},
|
||||
},
|
||||
ribbon: {
|
||||
start: 'شروع',
|
||||
insert: 'درج',
|
||||
|
||||
@@ -17,6 +17,20 @@
|
||||
import type enUS from './en-US';
|
||||
|
||||
const locale: typeof enUS = {
|
||||
toolbar: {
|
||||
heading: {
|
||||
normal: 'Normal',
|
||||
title: 'Titre',
|
||||
subTitle: 'Sous-titre',
|
||||
1: 'Titre 1',
|
||||
2: 'Titre 2',
|
||||
3: 'Titre 3',
|
||||
4: 'Titre 4',
|
||||
5: 'Titre 5',
|
||||
6: 'Titre 6',
|
||||
tooltip: 'Définir un titre',
|
||||
},
|
||||
},
|
||||
ribbon: {
|
||||
start: 'Démarrer',
|
||||
insert: 'Insérer',
|
||||
|
||||
@@ -17,6 +17,20 @@
|
||||
import type zhCN from './zh-CN';
|
||||
|
||||
const locale: typeof zhCN = {
|
||||
toolbar: {
|
||||
heading: {
|
||||
normal: 'Обычный текст',
|
||||
title: 'Заголовок',
|
||||
subTitle: 'Подзаголовок',
|
||||
1: 'Заголовок 1',
|
||||
2: 'Заголовок 2',
|
||||
3: 'Заголовок 3',
|
||||
4: 'Заголовок 4',
|
||||
5: 'Заголовок 5',
|
||||
6: 'Заголовок 6',
|
||||
tooltip: 'Установить заголовок',
|
||||
},
|
||||
},
|
||||
ribbon: {
|
||||
start: 'Начало',
|
||||
insert: 'Вставка',
|
||||
|
||||
@@ -17,6 +17,20 @@
|
||||
import type zhCN from './zh-CN';
|
||||
|
||||
const locale: typeof zhCN = {
|
||||
toolbar: {
|
||||
heading: {
|
||||
normal: 'Văn bản',
|
||||
title: 'Tiêu đề',
|
||||
subTitle: 'Tiêu đề phụ',
|
||||
1: 'Tiêu đề 1',
|
||||
2: 'Tiêu đề 2',
|
||||
3: 'Tiêu đề 3',
|
||||
4: 'Tiêu đề 4',
|
||||
5: 'Tiêu đề 5',
|
||||
6: 'Tiêu đề 6',
|
||||
tooltip: 'Đặt tiêu đề',
|
||||
},
|
||||
},
|
||||
ribbon: {
|
||||
start: 'Bắt đầu',
|
||||
insert: 'Chèn',
|
||||
|
||||
@@ -15,6 +15,20 @@
|
||||
*/
|
||||
|
||||
const locale = {
|
||||
toolbar: {
|
||||
heading: {
|
||||
normal: '正文',
|
||||
title: '标题',
|
||||
subTitle: '副标题',
|
||||
1: '标题1',
|
||||
2: '标题2',
|
||||
3: '标题3',
|
||||
4: '标题4',
|
||||
5: '标题5',
|
||||
6: '标题6',
|
||||
tooltip: '设置标题',
|
||||
},
|
||||
},
|
||||
ribbon: {
|
||||
start: '开始',
|
||||
insert: '插入',
|
||||
|
||||
@@ -17,6 +17,20 @@
|
||||
import type zhCN from './zh-CN';
|
||||
|
||||
const locale: typeof zhCN = {
|
||||
toolbar: {
|
||||
heading: {
|
||||
normal: '正文',
|
||||
title: '標題',
|
||||
subTitle: '副標題',
|
||||
1: '標題 1',
|
||||
2: '標題 2',
|
||||
3: '標題 3',
|
||||
4: '標題 4',
|
||||
5: '標題 5',
|
||||
6: '標題 6',
|
||||
tooltip: '設定標題',
|
||||
},
|
||||
},
|
||||
ribbon: {
|
||||
start: '開始',
|
||||
insert: '插入',
|
||||
|
||||
Reference in New Issue
Block a user