diff --git a/apps/spa/components/entities/EntityStrong.tsx b/apps/spa/components/entities/EntityStrong.tsx index 474b0cb9..c6249daa 100644 --- a/apps/spa/components/entities/EntityStrong.tsx +++ b/apps/spa/components/entities/EntityStrong.tsx @@ -1,16 +1,18 @@ import type { FC } from 'react'; import type { Strong } from '../../interpreter/entities'; +import { EntityEmphasis } from './EntityEmphasis'; interface Props { source: string; entity: Strong; } -export const EntityStrong: FC = ({ - source, - entity: { - child: { start, len }, - }, -}) => { - return {source.substring(start, start + len)}; +export const EntityStrong: FC = ({ source, entity: { child } }) => { + const content = + child.type === 'Text' ? ( + source.substring(child.start, child.start + child.len) + ) : ( + + ); + return {content}; }; diff --git a/apps/spa/interpreter/entities.ts b/apps/spa/interpreter/entities.ts index 702fa2f1..1b3def15 100644 --- a/apps/spa/interpreter/entities.ts +++ b/apps/spa/interpreter/entities.ts @@ -38,7 +38,7 @@ export interface CodeBlock extends BaseEntity { export interface Strong extends BaseEntity { type: 'Strong'; - child: Text; + child: Text | Emphasis; } export interface Emphasis extends BaseEntity { diff --git a/apps/spa/interpreter/parser.ts b/apps/spa/interpreter/parser.ts index d6d31500..9c6e00a2 100644 --- a/apps/spa/interpreter/parser.ts +++ b/apps/spa/interpreter/parser.ts @@ -232,6 +232,29 @@ const strong: P = regex(STRONG_REGEX).then(([match, { text, rest }]) => return [entity, { text, rest }]; }); +const STRONG_EM_REGEX = /^\*\*\*(.+?)\*\*\*/; + +const strongEmphasis: P = regex(STRONG_EM_REGEX).then(([match, { text, rest }]) => { + const [entire, content = ''] = match; + const entity: Strong = { + type: 'Strong', + start: text.length, + len: entire.length, + child: { + type: 'Emphasis', + start: text.length, + len: entire.length, + child: { + type: 'Text', + start: text.length + entire.indexOf(content), + len: content.length, + }, + }, + }; + text += entire; + return [entity, { text, rest }]; +}); + const URL_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)/; const autoUrl: P = regex(URL_REGEX).then(([match, { text, rest }]) => { @@ -610,7 +633,7 @@ const exprNodeToEntity = const ROLL_COMMAND = /^[.。]r\s*/; -const entity = choice([codeBlock, code, strong, emphasis, link, autoUrl, expression, span]); +const entity = choice([codeBlock, code, strongEmphasis, strong, emphasis, link, autoUrl, expression, span]); const message: P = many(entity).map((entityList) => entityList.reduce(mergeTextEntitiesReducer, [])); @@ -622,7 +645,18 @@ const rollCommand: P = new P((state, env) => { } return exprNodeToEntity(state)(result); }); - const entity = choice([codeBlock, code, strong, emphasis, link, autoUrl, expression, exprEntity, span]); + const entity = choice([ + codeBlock, + code, + strongEmphasis, + strong, + emphasis, + link, + autoUrl, + expression, + exprEntity, + span, + ]); const message = many(entity).map((entityList) => entityList.reduce(mergeTextEntitiesReducer, [])); return message.run(state, env); });