diff --git a/packages/@atjson/offset-annotations/src/annotations/blockquote.ts b/packages/@atjson/offset-annotations/src/annotations/blockquote.ts index 87d921183..bce10a2ec 100644 --- a/packages/@atjson/offset-annotations/src/annotations/blockquote.ts +++ b/packages/@atjson/offset-annotations/src/annotations/blockquote.ts @@ -1,7 +1,18 @@ import { BlockAnnotation } from "@atjson/document"; +import { TextAlignment } from "../utils/enums"; export class Blockquote extends BlockAnnotation<{ - inset?: "left" | "right"; + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + + /** + * Text alignment of the block. + */ + textAlignment?: TextAlignment; + /** * A named identifier used to quickly jump to this item */ diff --git a/packages/@atjson/offset-annotations/src/annotations/caption-source.ts b/packages/@atjson/offset-annotations/src/annotations/caption-source.ts deleted file mode 100644 index b9d0048b8..000000000 --- a/packages/@atjson/offset-annotations/src/annotations/caption-source.ts +++ /dev/null @@ -1,32 +0,0 @@ -import Document from "@atjson/document"; - -import { Bold } from "./bold"; -import { Italic } from "./italic"; -import { LineBreak } from "./line-break"; -import { Link } from "./link"; -import { List } from "./list"; -import { ListItem } from "./list-item"; -import { Paragraph } from "./paragraph"; -import { SmallCaps } from "./small-caps"; -import { Strikethrough } from "./strikethrough"; -import { Subscript } from "./subscript"; -import { Superscript } from "./superscript"; -import { Underline } from "./underline"; - -export class CaptionSource extends Document { - static contentType = "application/vnd.atjson+offset-caption"; - static schema = [ - Bold, - Italic, - LineBreak, - Link, - List, - ListItem, - Paragraph, - SmallCaps, - Subscript, - Strikethrough, - Superscript, - Underline, - ]; -} diff --git a/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts b/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts index 7cc580788..22ce4939e 100644 --- a/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts @@ -1,10 +1,30 @@ import { BlockAnnotation } from "@atjson/document"; export class CerosEmbed extends BlockAnnotation<{ + /** + * The URL to the Ceros experience. + */ url: string; + + /** + * The aspect ratio, as a fraction of the embed, which + * is used so the embed can be scaled automatically + * by the Ceros script tag. + */ aspectRatio: number; + + /** + * The mobile aspect ratio of the embed, which is chosen + * by Ceros when on smaller screen sizes. + */ mobileAspectRatio?: number; - size?: "small" | "medium" | "large"; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + /** * A named identifier used to quickly jump to this item */ diff --git a/packages/@atjson/offset-annotations/src/annotations/cne-audio-embed.ts b/packages/@atjson/offset-annotations/src/annotations/cne-audio-embed.ts index 6cc164be0..e3fa044b9 100644 --- a/packages/@atjson/offset-annotations/src/annotations/cne-audio-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/cne-audio-embed.ts @@ -6,9 +6,31 @@ export enum AudioEnvironments { } export class CneAudioEmbed extends BlockAnnotation<{ + /** + * Indicates the environment that the audio was published in. + */ audioEnv: AudioEnvironments; + + /** + * The type of audio embed. + */ audioType: string; + + /** + * The unique id of the audio, used to embed the + * podcast / episode / etc. + */ audioId: string; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + + /** + * A named identifier used to quickly jump to this item + */ anchorName?: string; }> { static vendorPrefix = "offset"; diff --git a/packages/@atjson/offset-annotations/src/annotations/facebook-embed.ts b/packages/@atjson/offset-annotations/src/annotations/facebook-embed.ts index e34dd733b..a89b4f5da 100644 --- a/packages/@atjson/offset-annotations/src/annotations/facebook-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/facebook-embed.ts @@ -1,6 +1,33 @@ -import { IframeEmbed } from "./iframe-embed"; +import { BlockAnnotation } from "@atjson/document"; -export class FacebookEmbed extends IframeEmbed { +export class FacebookEmbed extends BlockAnnotation<{ + /** + * The URL to the embed on www.facebook.com + */ + url: string; + + /** + * If set to true, this hides the text attached to a photo post. + */ + hideText?: boolean; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + + /** + * A named identifier used to quickly jump to this item + */ + anchorName?: string; + + /** + * The post content at the time of embedding, ususally + * a textual representation of the content with some links. + */ + content?: string; +}> { static type = "facebook-embed"; static vendorPrefix = "offset"; } diff --git a/packages/@atjson/offset-annotations/src/annotations/firework-embed.ts b/packages/@atjson/offset-annotations/src/annotations/firework-embed.ts index e1de47cd9..4aec22b24 100644 --- a/packages/@atjson/offset-annotations/src/annotations/firework-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/firework-embed.ts @@ -1,9 +1,28 @@ import { BlockAnnotation } from "@atjson/document"; export class FireworkEmbed extends BlockAnnotation<{ + /** + * The id of the Firework video playlist. + */ playlistId: string; + + /** + * The channel used to track Firework video embeds. + */ channel?: string; + + /** + * Deterimines how the video should open when they + * are clicked. + */ open?: "default" | "_self" | "_modal" | "_blank"; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + /** * A named identifier used to quickly jump to this item */ diff --git a/packages/@atjson/offset-annotations/src/annotations/group.ts b/packages/@atjson/offset-annotations/src/annotations/group.ts index 8e3f2d5e5..83b692ae4 100644 --- a/packages/@atjson/offset-annotations/src/annotations/group.ts +++ b/packages/@atjson/offset-annotations/src/annotations/group.ts @@ -18,7 +18,19 @@ import { BlockAnnotation } from "@atjson/document"; */ export class Group extends BlockAnnotation< T & { + /** + * Art direction information about how the group should + * be laid out. Properties here can determine whether + * media should be shown as a diptych, masonry, stacked, etc. + */ artDirection: string; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + /** * A named identifier used to quickly jump to this item */ diff --git a/packages/@atjson/offset-annotations/src/annotations/heading.ts b/packages/@atjson/offset-annotations/src/annotations/heading.ts index 292dbf24c..9cfb8760a 100644 --- a/packages/@atjson/offset-annotations/src/annotations/heading.ts +++ b/packages/@atjson/offset-annotations/src/annotations/heading.ts @@ -1,8 +1,25 @@ import { BlockAnnotation } from "@atjson/document"; +import { TextAlignment } from "../utils/enums"; export class Heading extends BlockAnnotation<{ + /** + * The heading level, from 1-6 as mapped to from + * DOM headings. These should correspond with + * accessiblity levels. + */ level: 1 | 2 | 3 | 4 | 5 | 6; - alignment?: "start" | "center" | "end" | "justify"; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + + /** + * Text alignment of the block. + */ + textAlignment?: TextAlignment; + /** * A named identifier used to quickly jump to this item */ diff --git a/packages/@atjson/offset-annotations/src/annotations/horizontal-rule.ts b/packages/@atjson/offset-annotations/src/annotations/horizontal-rule.ts index 0bf07f56d..4c2dc2900 100644 --- a/packages/@atjson/offset-annotations/src/annotations/horizontal-rule.ts +++ b/packages/@atjson/offset-annotations/src/annotations/horizontal-rule.ts @@ -1,6 +1,13 @@ import { BlockAnnotation } from "@atjson/document"; -export class HorizontalRule extends BlockAnnotation { +export class HorizontalRule extends BlockAnnotation<{ + /** + * Indicates a stylistic alternate for a horizontal + * rule, which can be used to divide content for + * special reports or stories. + */ + style?: string; +}> { static vendorPrefix = "offset"; static type = "horizontal-rule"; } diff --git a/packages/@atjson/offset-annotations/src/annotations/iframe-embed.ts b/packages/@atjson/offset-annotations/src/annotations/iframe-embed.ts index a675add16..cf3bb2ea6 100644 --- a/packages/@atjson/offset-annotations/src/annotations/iframe-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/iframe-embed.ts @@ -1,15 +1,43 @@ import { BlockAnnotation } from "@atjson/document"; export class IframeEmbed extends BlockAnnotation<{ + /** + * The embed URL to host in the iframe. + */ url: string; + + /** + * The width of the embed, as a valid CSS unit + * (rem, em, pixels, percentages). + */ width?: string; + + /** + * The height of the embed, as a valid CSS unit + * (rem, em, pixels, percentages). + */ height?: string; + /** - * Refers to a slice instead of being an - * embedded document. + * Refers to a slice instead of being an embedded document. */ caption?: string; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + * + * For iframe embeds, this may be used to flex an iframe + * with sizing using percentages. + */ + layout?: string; + + /** + * Sandbox properties that indicate what permissions are required + * by the embedded context so it can run correctly. + */ sandbox?: string; + /** * A named identifier used to quickly jump to this item */ diff --git a/packages/@atjson/offset-annotations/src/annotations/image.ts b/packages/@atjson/offset-annotations/src/annotations/image.ts index 432c76ca0..2c075c577 100644 --- a/packages/@atjson/offset-annotations/src/annotations/image.ts +++ b/packages/@atjson/offset-annotations/src/annotations/image.ts @@ -1,9 +1,25 @@ import { ObjectAnnotation } from "@atjson/document"; export class Image extends ObjectAnnotation<{ + /** + * The URL to the image. + */ url: string; + + /** + * The title of the image, provided for compatibility + * with markdown and HTML. + */ title?: string; + + /** + * A description of the image, used for assistive + * technology to provide information to someone + * that may need help describing the contents of + * the image. + */ description?: string; + /** * A named identifier used to quickly jump to this item */ diff --git a/packages/@atjson/offset-annotations/src/annotations/index.ts b/packages/@atjson/offset-annotations/src/annotations/index.ts index aa4607f32..d49f16959 100644 --- a/packages/@atjson/offset-annotations/src/annotations/index.ts +++ b/packages/@atjson/offset-annotations/src/annotations/index.ts @@ -1,6 +1,5 @@ export * from "./blockquote"; export * from "./bold"; -export * from "./caption-source"; export * from "./ceros-embed"; export * from "./cne-audio-embed"; export * from "./cne-event-registration-embed"; @@ -34,7 +33,6 @@ export * from "./strikethrough"; export * from "./subscript"; export * from "./superscript"; export * from "./table"; -export * from "./telegram-embed"; export * from "./tiktok-embed"; export * from "./twitter-embed"; export * from "./underline"; diff --git a/packages/@atjson/offset-annotations/src/annotations/instagram-embed.ts b/packages/@atjson/offset-annotations/src/annotations/instagram-embed.ts index d75d0ee4a..f0db4c28a 100644 --- a/packages/@atjson/offset-annotations/src/annotations/instagram-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/instagram-embed.ts @@ -1,6 +1,34 @@ -import { IframeEmbed } from "./iframe-embed"; +import { BlockAnnotation } from "@atjson/document"; -export class InstagramEmbed extends IframeEmbed { +export class InstagramEmbed extends BlockAnnotation<{ + /** + * The URL to the post on www.instagram.com + */ + url: string; + + /** + * If set to false, this excludes the caption attached to the post. + * This maps to the `captioned` option on the embed. + */ + excludePostCaption?: boolean; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + + /** + * A named identifier used to quickly jump to this item + */ + anchorName?: string; + + /** + * The post content at the time of embedding, ususally + * a textual representation of the content with some links. + */ + content?: string; +}> { static type = "instagram-embed"; static vendorPrefix = "offset"; } diff --git a/packages/@atjson/offset-annotations/src/annotations/link.ts b/packages/@atjson/offset-annotations/src/annotations/link.ts index 20a124f09..043d016ea 100644 --- a/packages/@atjson/offset-annotations/src/annotations/link.ts +++ b/packages/@atjson/offset-annotations/src/annotations/link.ts @@ -1,13 +1,41 @@ import { EdgeBehaviour, InlineAnnotation } from "@atjson/document"; export class Link extends InlineAnnotation<{ + /** + * The URL of the link. + */ url: string; + + /** + * Optional title of the link, provided for compatibility + * with markdown and HTML. + */ title?: string; + + /** + * Metadata about the relationship of the link to the current + * page. This maps directly to the `rel` property on anchor + * tags in HTML. + */ rel?: string; + + /** + * Maps to the HTML target property on links, which provides + * control whether a link should open in a new tab or in the + * same tab. + */ target?: string; + + /** + * A flag to mark a link as an affiliate link. + */ isAffiliateLink?: boolean; + + /** + * A flag to mark a link as generated automatically + * via a pattern or script. + */ isAutogenerated?: boolean; - linkStyle?: "button"; }> { static vendorPrefix = "offset"; static type = "link"; diff --git a/packages/@atjson/offset-annotations/src/annotations/list.ts b/packages/@atjson/offset-annotations/src/annotations/list.ts index a2cea0956..0570d9981 100644 --- a/packages/@atjson/offset-annotations/src/annotations/list.ts +++ b/packages/@atjson/offset-annotations/src/annotations/list.ts @@ -1,11 +1,41 @@ import { BlockAnnotation } from "@atjson/document"; export class List extends BlockAnnotation<{ + /** + * The type of list— out of the box, atjson + * understands "bulleted" and "numbered" lists. + */ type: string; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + + /** + * Used to specify the delimiter character used + * for the list if it's a bulleted list. + */ delimiter?: string; + + /** + * This is a markdown feature that has made its way + * into atjson for full markdown compatibility, indicating + * that the list items should be wrapped in paragraphs. + * + * We don't really recommend this, since it's such a + * finicky way of managing lists for writers. Not really + * something that's necessary. + */ loose?: boolean; - level?: number; + + /** + * If this is a numbered list, this indicates what number + * the list should start at. + */ startsAt?: number; + /** * A named identifier used to quickly jump to this item */ diff --git a/packages/@atjson/offset-annotations/src/annotations/paragraph.ts b/packages/@atjson/offset-annotations/src/annotations/paragraph.ts index 7d92e17ce..14f5c31f9 100644 --- a/packages/@atjson/offset-annotations/src/annotations/paragraph.ts +++ b/packages/@atjson/offset-annotations/src/annotations/paragraph.ts @@ -1,9 +1,26 @@ import { BlockAnnotation } from "@atjson/document"; +import { TextAlignment } from "../utils/enums"; export class Paragraph< T = { + /** + * A list of decorations to apply to the paragraph. + * This may be something like a drop cap or other + * decorative flourish. + */ decorations?: string[]; - alignment?: "start" | "center" | "end" | "justify"; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + + /** + * Text alignment of the block. + */ + textAlignment?: TextAlignment; + /** * A named identifier used to quickly jump to this item */ diff --git a/packages/@atjson/offset-annotations/src/annotations/pinterest-embed.ts b/packages/@atjson/offset-annotations/src/annotations/pinterest-embed.ts index eb6a63990..376a036cc 100644 --- a/packages/@atjson/offset-annotations/src/annotations/pinterest-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/pinterest-embed.ts @@ -1,6 +1,25 @@ -import { IframeEmbed } from "./iframe-embed"; +import { BlockAnnotation } from "@atjson/document"; -export class PinterestEmbed extends IframeEmbed { +export class PinterestEmbed extends BlockAnnotation<{ + url: string; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + + /** + * A named identifier used to quickly jump to this item + */ + anchorName?: string; + + /** + * The post content at the time of embedding, ususally + * a textual representation of the content with some links. + */ + content?: string; +}> { static type = "pinterest-embed"; static vendorPrefix = "offset"; } diff --git a/packages/@atjson/offset-annotations/src/annotations/pullquote.ts b/packages/@atjson/offset-annotations/src/annotations/pullquote.ts index c16f598ca..739ab9208 100644 --- a/packages/@atjson/offset-annotations/src/annotations/pullquote.ts +++ b/packages/@atjson/offset-annotations/src/annotations/pullquote.ts @@ -1,6 +1,12 @@ import { BlockAnnotation } from "@atjson/document"; export class Pullquote extends BlockAnnotation<{ + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + /** * A named identifier used to quickly jump to this item */ diff --git a/packages/@atjson/offset-annotations/src/annotations/sidebar.ts b/packages/@atjson/offset-annotations/src/annotations/sidebar.ts index cdd3f39a1..cacf8d8b0 100644 --- a/packages/@atjson/offset-annotations/src/annotations/sidebar.ts +++ b/packages/@atjson/offset-annotations/src/annotations/sidebar.ts @@ -4,10 +4,14 @@ import { BlockAnnotation } from "@atjson/document"; * Sidebar annotations are alignable and may be used to display * content within a body that is graphically separate but with * contextual connection. - **/ - + */ export class Sidebar extends BlockAnnotation<{ - inset: "left" | "right"; + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + /** * A named identifier used to quickly jump to this item */ diff --git a/packages/@atjson/offset-annotations/src/annotations/table.ts b/packages/@atjson/offset-annotations/src/annotations/table.ts index beddfc615..c8569b92b 100644 --- a/packages/@atjson/offset-annotations/src/annotations/table.ts +++ b/packages/@atjson/offset-annotations/src/annotations/table.ts @@ -1,4 +1,5 @@ import { BlockAnnotation } from "@atjson/document"; +import { TextAlignment } from "../utils/enums"; /** * A table is a way of displaying tabular or database-like data. @@ -32,7 +33,7 @@ export class Table extends BlockAnnotation<{ columns: Array<{ name: string; slice?: string; - textAlign?: "left" | "right" | "center"; + textAlignment?: TextAlignment; }>; /** diff --git a/packages/@atjson/offset-annotations/src/annotations/telegram-embed.ts b/packages/@atjson/offset-annotations/src/annotations/telegram-embed.ts deleted file mode 100644 index 66e10588f..000000000 --- a/packages/@atjson/offset-annotations/src/annotations/telegram-embed.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IframeEmbed } from "./iframe-embed"; - -export class TelegramEmbed extends IframeEmbed { - static type = "telegram-embed"; - static vendorPrefix = "offset"; -} diff --git a/packages/@atjson/offset-annotations/src/annotations/tiktok-embed.ts b/packages/@atjson/offset-annotations/src/annotations/tiktok-embed.ts index 61f82b02c..2b51f075b 100644 --- a/packages/@atjson/offset-annotations/src/annotations/tiktok-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/tiktok-embed.ts @@ -1,6 +1,28 @@ -import { IframeEmbed } from "./iframe-embed"; +import { BlockAnnotation } from "@atjson/document"; -export class TikTokEmbed extends IframeEmbed { +export class TikTokEmbed extends BlockAnnotation<{ + /** + * The URL to the TikTok video on www.tiktok.com + */ + url: string; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + + /** + * A named identifier used to quickly jump to this item + */ + anchorName?: string; + + /** + * The post content at the time of embedding, ususally + * a textual representation of the content with some links. + */ + content?: string; +}> { static type = "tiktok-embed"; static vendorPrefix = "offset"; } diff --git a/packages/@atjson/offset-annotations/src/annotations/twitter-embed.ts b/packages/@atjson/offset-annotations/src/annotations/twitter-embed.ts index b9268516e..33466e706 100644 --- a/packages/@atjson/offset-annotations/src/annotations/twitter-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/twitter-embed.ts @@ -1,6 +1,28 @@ -import { IframeEmbed } from "./iframe-embed"; +import { BlockAnnotation } from "@atjson/document"; -export class TwitterEmbed extends IframeEmbed { +export class TwitterEmbed extends BlockAnnotation<{ + /** + * The embed URL to the post on www.x.com / www.twitter.com + */ + url: string; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + + /** + * A named identifier used to quickly jump to this item + */ + anchorName?: string; + + /** + * The post content at the time of embedding, ususally + * a textual representation of the content with some links. + */ + content?: string; +}> { static type = "twitter-embed"; static vendorPrefix = "offset"; } diff --git a/packages/@atjson/offset-annotations/src/annotations/video-embed.ts b/packages/@atjson/offset-annotations/src/annotations/video-embed.ts index 8a0005518..bdc0cad24 100644 --- a/packages/@atjson/offset-annotations/src/annotations/video-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/video-embed.ts @@ -6,32 +6,44 @@ export class VideoEmbed extends BlockAnnotation<{ * The embed URL of the video */ url: string; + /** * The provider of the Video */ provider: VideoURLs.Provider; + /** * A normalized aspect ratio of the video, constrained to * a list of aspect ratios */ aspectRatio?: ReturnType; + /** * The natural width of the video, as returned by an * oEmbed endpoint. * @deprecated */ width?: number; + /** * The natural height of the video, as returned by an * oEmbed endpoint. * @deprecated */ height?: number; + /** * Refers to a slice instead of being an * embedded document. */ caption?: string; + + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; + /** * A named identifier used to quickly jump to this item */ diff --git a/packages/@atjson/offset-annotations/src/utils/convert-html-tables.ts b/packages/@atjson/offset-annotations/src/utils/convert-html-tables.ts index 3ab396631..669fd8443 100644 --- a/packages/@atjson/offset-annotations/src/utils/convert-html-tables.ts +++ b/packages/@atjson/offset-annotations/src/utils/convert-html-tables.ts @@ -6,7 +6,12 @@ import { TextAnnotation, } from "@atjson/document"; -import OffsetSource, { DataSet, Table, ColumnType } from "../index"; +import OffsetSource, { + DataSet, + Table, + ColumnType, + TextAlignment, +} from "../index"; function extractPlainContents( doc: OffsetSource, @@ -72,8 +77,13 @@ function extractAlignment(tableCell: Annotation<{ style: string }>) { /(text-align: ?(?left|right|center))/ ); - if (match?.groups?.alignment) { - return match.groups.alignment as "left" | "right" | "center"; + switch (match?.groups?.alignment) { + case "left": + return TextAlignment.Start; + case "right": + return TextAlignment.End; + case "center": + return TextAlignment.Center; } } @@ -135,7 +145,7 @@ export function convertHTMLTablesToDataSet( let alignment = extractAlignment(headCell); if (alignment) { - columnConfig.textAlign = alignment; + columnConfig.textAlignment = alignment; } columnConfigs.push(columnConfig); @@ -182,7 +192,7 @@ export function convertHTMLTablesToDataSet( let alignment = extractAlignment(bodyCell); if (alignment) { - columnConfig.textAlign = alignment; + columnConfig.textAlignment = alignment; } columnConfigs[index] = columnConfig; diff --git a/packages/@atjson/offset-annotations/src/utils/enums.ts b/packages/@atjson/offset-annotations/src/utils/enums.ts new file mode 100644 index 000000000..bc83e033e --- /dev/null +++ b/packages/@atjson/offset-annotations/src/utils/enums.ts @@ -0,0 +1,6 @@ +export enum TextAlignment { + Start = "start", + End = "end", + Center = "center", + Justify = "justify", +} diff --git a/packages/@atjson/offset-annotations/src/utils/index.ts b/packages/@atjson/offset-annotations/src/utils/index.ts index 15b398d33..b76132001 100644 --- a/packages/@atjson/offset-annotations/src/utils/index.ts +++ b/packages/@atjson/offset-annotations/src/utils/index.ts @@ -2,10 +2,12 @@ import { getClosestAspectRatio } from "./aspect-ratios"; import * as SocialURLs from "./social-urls"; import * as VideoURLs from "./video-urls"; import { convertHTMLTablesToDataSet } from "./convert-html-tables"; +import { TextAlignment } from "./enums"; export { convertHTMLTablesToDataSet, getClosestAspectRatio, SocialURLs, + TextAlignment, VideoURLs, }; diff --git a/packages/@atjson/offset-annotations/src/utils/social-urls.ts b/packages/@atjson/offset-annotations/src/utils/social-urls.ts index c1768a774..a6093cc25 100644 --- a/packages/@atjson/offset-annotations/src/utils/social-urls.ts +++ b/packages/@atjson/offset-annotations/src/utils/social-urls.ts @@ -4,7 +4,6 @@ import { GiphyEmbed, InstagramEmbed, PinterestEmbed, - TelegramEmbed, TikTokEmbed, TwitterEmbed, } from "../annotations"; @@ -127,9 +126,14 @@ function normalizeInstagramReelURL(url: IUrl) { // Twitter // - www.twitter.com/:handle/status/:tweetId // - m.twitter.com/:handle/status/:tweetId +// - www.x.com/:handle/status/:postId +// - m.x.com/:handle/status/:postId function isTwitterURL(url: IUrl) { return ( - (url.host === "twitter.com" || /.*\.twitter\.com$/.test(url.host)) && + (url.host === "x.com" || + /.*\.x\.com$/.test(url.host) || + url.host === "twitter.com" || + /.*\.twitter\.com$/.test(url.host)) && /\/[^\/]+\/status\/[^\/]+/.test(url.pathname) ); } @@ -356,23 +360,6 @@ function normalizeTikTokUrl(url: IUrl) { }; } -// Telegram URLs -// Needs to covert post URL (https://t.me/:channelSlug/:postId) to post slug (:channelSlug/:postId) -// Docs here https://core.telegram.org/widgets/post - -function isTelegramUrl(url: IUrl) { - return url.host === "t.me"; -} - -function normalizeTelegramUrl(url: IUrl) { - let [cahnnelSlug, postId] = without(url.pathname.split("/"), ""); - return { - Class: TelegramEmbed, - attributes: { - url: `${cahnnelSlug}/${postId}`, - }, - }; -} function isRedditURL(url: IUrl) { return ( (url.host === "www.redditmedia.com" && url.pathname.startsWith("/r/")) || @@ -413,15 +400,7 @@ function normalizeRedditURL(url: IUrl) { }; } -export function identify(url: IUrl): { - attributes: { - url: string; - width?: string; - height?: string; - sandbox?: string; - }; - Class: typeof IframeEmbed; -} | null { +export function identify(url: IUrl) { if (isRedditURL(url)) { return normalizeRedditURL(url); } @@ -465,9 +444,5 @@ export function identify(url: IUrl): { return normalizeTikTokUrl(url); } - if (isTelegramUrl(url)) { - return normalizeTelegramUrl(url); - } - return null; } diff --git a/packages/@atjson/offset-annotations/test/social-urls.test.ts b/packages/@atjson/offset-annotations/test/social-urls.test.ts index dbce5c9e7..c7b18cf3e 100644 --- a/packages/@atjson/offset-annotations/test/social-urls.test.ts +++ b/packages/@atjson/offset-annotations/test/social-urls.test.ts @@ -1,4 +1,4 @@ -import { IframeEmbed, TelegramEmbed, SocialURLs, InstagramEmbed } from "../src"; +import { IframeEmbed, SocialURLs, InstagramEmbed, TwitterEmbed } from "../src"; describe("SocialURLs", () => { describe("identify Spotify", () => { @@ -141,28 +141,6 @@ describe("SocialURLs", () => { }); }); - describe("identify Telegram", () => { - test.each([ - [ - "https://t.me/voguerussia/8714/", - { - url: "voguerussia/8714", - }, - ], - [ - "http://t.me/tatlerbutler/3416", - { - url: "tatlerbutler/3416", - }, - ], - ])("%s", (url, attributes) => { - expect(SocialURLs.identify(new URL(url))).toMatchObject({ - Class: TelegramEmbed, - attributes, - }); - }); - }); - describe("identify Reddit", () => { test.each([ [ @@ -224,4 +202,32 @@ describe("SocialURLs", () => { }); }); }); + + describe("identify Tweets", () => { + test.each([ + [ + "https://twitter.com/dril/status/1696601385385816223", + { + url: "https://twitter.com/dril/status/1696601385385816223", + }, + ], + [ + "https://x.com/dril/status/1696601385385816223", + { + url: "https://twitter.com/dril/status/1696601385385816223", + }, + ], + [ + "https://www.twitter.com/dril/status/1696601385385816223", + { + url: "https://twitter.com/dril/status/1696601385385816223", + }, + ], + ])("%s", (url, attributes) => { + expect(SocialURLs.identify(new URL(url))).toMatchObject({ + Class: TwitterEmbed, + attributes, + }); + }); + }); }); diff --git a/packages/@atjson/renderer-commonmark/src/index.ts b/packages/@atjson/renderer-commonmark/src/index.ts index 80340b127..2c0044e62 100644 --- a/packages/@atjson/renderer-commonmark/src/index.ts +++ b/packages/@atjson/renderer-commonmark/src/index.ts @@ -11,6 +11,7 @@ import { List, Paragraph, Table, + TextAlignment, } from "@atjson/offset-annotations"; import Renderer, { Context } from "@atjson/renderer-hir"; import type { Block, Mark } from "@atjson/document"; @@ -776,11 +777,12 @@ export default class CommonmarkRenderer extends Renderer { header: string; rows: string[]; width: number; - textAlign?: "left" | "center" | "right"; + textAlignment?: TextAlignment; } > = {}; - for (let { name, slice: sliceId, textAlign } of table.attributes.columns) { + for (let { name, slice: sliceId, textAlignment } of table.attributes + .columns) { let headerText = ""; if (table.attributes.showColumnHeaders) { if (sliceId) { @@ -797,7 +799,7 @@ export default class CommonmarkRenderer extends Renderer { header: headerText.replace(/\n/g, " "), rows: [], width: Math.max(headerText.length, 1), - textAlign, + textAlignment, }; } @@ -830,16 +832,22 @@ export default class CommonmarkRenderer extends Renderer { let headerRow = "|"; let separatorRow = "|"; - for (let { name, textAlign } of table.attributes.columns) { + for (let { name, textAlignment } of table.attributes.columns) { let headerText = columns[name].header; let columnWidth = columns[name].width; headerRow += " " + headerText + " ".repeat(columnWidth - headerText.length) + " |"; let leftDecoration = - textAlign === "left" || textAlign === "center" ? ":" : " "; + textAlignment === TextAlignment.Start || + textAlignment === TextAlignment.Center + ? ":" + : " "; let rightDecoration = - textAlign === "center" || textAlign === "right" ? ":" : " "; + textAlignment === TextAlignment.Center || + textAlignment === TextAlignment.End + ? ":" + : " "; separatorRow += leftDecoration + "-".repeat(columnWidth) + rightDecoration + "|"; } diff --git a/packages/@atjson/renderer-commonmark/test/table.test.ts b/packages/@atjson/renderer-commonmark/test/table.test.ts index 9ec657e60..33c4c4d96 100644 --- a/packages/@atjson/renderer-commonmark/test/table.test.ts +++ b/packages/@atjson/renderer-commonmark/test/table.test.ts @@ -1,5 +1,5 @@ import { Block, deserialize } from "@atjson/document"; -import OffsetSource, { Table } from "@atjson/offset-annotations"; +import OffsetSource, { Table, TextAlignment } from "@atjson/offset-annotations"; import CommonmarkRenderer from "../src"; function testTable( @@ -554,10 +554,18 @@ describe("tables", () => { test("mixed alignment", () => { let document = testTable({ columns: [ - { name: "name", slice: "M00000000", textAlign: "left" }, - { name: "age", slice: "M00000001", textAlign: "right" }, + { + name: "name", + slice: "M00000000", + textAlignment: TextAlignment.Start, + }, + { name: "age", slice: "M00000001", textAlignment: TextAlignment.End }, { name: "job", slice: "M00000002" }, - { name: "notes", slice: "M00000005", textAlign: "center" }, + { + name: "notes", + slice: "M00000005", + textAlignment: TextAlignment.Center, + }, ], showColumnHeaders: true, }); diff --git a/packages/@atjson/renderer-html/src/index.ts b/packages/@atjson/renderer-html/src/index.ts index 50c3369ee..8b5a5286e 100644 --- a/packages/@atjson/renderer-html/src/index.ts +++ b/packages/@atjson/renderer-html/src/index.ts @@ -14,6 +14,7 @@ import { Paragraph, Section, Table, + TextAlignment, TikTokEmbed, } from "@atjson/offset-annotations"; import { Mark, Block } from "@atjson/document"; @@ -42,6 +43,13 @@ const CneAudioEnvironments = { [AudioEnvironments.Sandbox]: `https://embed-audio-sandbox.cnevids.com`, }; +const TableTextAlign = { + [TextAlignment.Start]: "left", + [TextAlignment.End]: "right", + [TextAlignment.Center]: "center", + [TextAlignment.Justify]: "center", +}; + export default class HTMLRenderer extends Renderer { /** * Renders an HTML string from an object. @@ -181,8 +189,8 @@ export default class HTMLRenderer extends Renderer { *Heading(heading: Block) { let style: string | undefined; - if (heading.attributes.alignment) { - style = this.textAlign(heading.attributes.alignment); + if (heading.attributes.textAlignment) { + style = this.textAlign(heading.attributes.textAlignment); } return yield* this.$(`h${heading.attributes.level}`, { id: heading.attributes.anchorName, @@ -239,8 +247,8 @@ export default class HTMLRenderer extends Renderer { *Paragraph(paragraph: Block) { let style: string | undefined; - if (paragraph.attributes.alignment) { - style = this.textAlign(paragraph.attributes.alignment); + if (paragraph.attributes.textAlignment) { + style = this.textAlign(paragraph.attributes.textAlignment); } return yield* this.$("p", { id: paragraph.attributes.anchorName, style }); } @@ -285,7 +293,7 @@ export default class HTMLRenderer extends Renderer { let header = ""; if (table.attributes.showColumnHeaders) { header += ""; - for (let { name, slice: sliceId, textAlign } of table.attributes + for (let { name, slice: sliceId, textAlignment } of table.attributes .columns) { let headerText = name; if (sliceId) { @@ -300,9 +308,10 @@ export default class HTMLRenderer extends Renderer { headerText = this.render(slice); } - header += `${headerText}`; } @@ -312,7 +321,7 @@ export default class HTMLRenderer extends Renderer { let body = ""; for (let record of dataSet.attributes.records) { body += ""; - for (let { name, textAlign } of table.attributes.columns) { + for (let { name, textAlignment } of table.attributes.columns) { let cellText = ""; let sliceId = record[name]?.slice; if (sliceId) { @@ -333,7 +342,9 @@ export default class HTMLRenderer extends Renderer { } body += `${cellText}`; } @@ -348,11 +359,17 @@ export default class HTMLRenderer extends Renderer { let parts = embed.attributes.url.split("/"); let username = parts[parts.length - 3]; let videoId = parts[parts.length - 1]; + let slice = + embed.attributes.content != null && + this.getSlice(embed.attributes.content); + let content = slice + ? this.render(slice) + : `${username}`; return `
${username}
`; + }" data-video-id="${videoId}" style="max-width: 605px;min-width: 325px;">
${content}
`; } // CNE Audio embed @@ -372,12 +389,16 @@ export default class HTMLRenderer extends Renderer { return yield* this.$("u"); } - protected textAlign(alignment: "start" | "center" | "end" | "justify") { - if (alignment === "start") { - return `text-align:left;`; - } else if (alignment === "end") { - return `text-align:right;`; + protected textAlign(alignment: TextAlignment): string { + switch (alignment) { + case TextAlignment.Start: + return `text-align:start;`; + case TextAlignment.End: + return `text-align:end;`; + case TextAlignment.Center: + return `text-align:center;`; + case TextAlignment.Justify: + return `text-align:justify;`; } - return `text-align:${alignment};`; } } diff --git a/packages/@atjson/renderer-html/test/renderer.test.ts b/packages/@atjson/renderer-html/test/renderer.test.ts index f83f6e47c..887519abe 100644 --- a/packages/@atjson/renderer-html/test/renderer.test.ts +++ b/packages/@atjson/renderer-html/test/renderer.test.ts @@ -21,8 +21,8 @@ import OffsetSource, { Strikethrough, Subscript, Superscript, - TikTokEmbed, Underline, + TextAlignment, } from "@atjson/offset-annotations"; import { ParseAnnotation, serialize } from "@atjson/document"; import Renderer from "../src"; @@ -103,11 +103,11 @@ describe("renderer-html", () => { describe("alignment", () => { describe.each([ - ["left", "start"], - ["center", "center"], - ["right", "end"], - ["justify", "justify"], - ] as const)("%s", (textAlign, alignment) => { + ["start", TextAlignment.Start], + ["center", TextAlignment.Center], + ["end", TextAlignment.End], + ["justify", TextAlignment.Justify], + ] as const)("%s", (textAlign, textAlignment) => { test.each([1, 2, 3, 4, 5, 6] as const)("level %s", (level) => { let doc = new OffsetSource({ content: "Hello", @@ -117,7 +117,7 @@ describe("renderer-html", () => { end: 5, attributes: { level, - alignment, + textAlignment, }, }), ], @@ -399,18 +399,18 @@ describe("renderer-html", () => { describe("alignment", () => { describe.each([ - ["left", "start"], - ["center", "center"], - ["right", "end"], - ["justify", "justify"], - ] as const)("%s", (textAlign, alignment) => { + ["start", TextAlignment.Start], + ["center", TextAlignment.Center], + ["end", TextAlignment.End], + ["justify", TextAlignment.Justify], + ] as const)("%s", (textAlign, textAlignment) => { let doc = new OffsetSource({ content: "Hello", annotations: [ new Paragraph({ start: 0, end: 5, - attributes: { alignment }, + attributes: { textAlignment }, }), ], }); @@ -537,29 +537,6 @@ describe("renderer-html", () => { }); }); - test("tiktok", () => { - let doc = new OffsetSource({ - content: "\uFFFC", - annotations: [ - new TikTokEmbed({ - start: 0, - end: 1, - attributes: { - url: "https://www.tiktok.com/@vogueitalia/video/6771026615137750277", - }, - }), - new ParseAnnotation({ - start: 0, - end: 1, - }), - ], - }); - - expect(Renderer.render(doc)).toEqual( - `
@vogueitalia
` - ); - }); - test("cneaudio", () => { let docProductionEnv = new OffsetSource({ content: "\uFFFC", diff --git a/packages/@atjson/renderer-html/test/table.test.ts b/packages/@atjson/renderer-html/test/table.test.ts index d4d0f10a0..c8c774f71 100644 --- a/packages/@atjson/renderer-html/test/table.test.ts +++ b/packages/@atjson/renderer-html/test/table.test.ts @@ -1,5 +1,5 @@ import { Block, deserialize } from "@atjson/document"; -import OffsetSource, { Table } from "@atjson/offset-annotations"; +import OffsetSource, { Table, TextAlignment } from "@atjson/offset-annotations"; import HtmlRenderer from "../src"; function testTable( @@ -328,10 +328,18 @@ describe("tables", () => { test("mixed alignment", () => { let document = testTable({ columns: [ - { name: "name", slice: "M00000000", textAlign: "left" }, - { name: "age", slice: "M00000001", textAlign: "right" }, + { + name: "name", + slice: "M00000000", + textAlignment: TextAlignment.Start, + }, + { name: "age", slice: "M00000001", textAlignment: TextAlignment.End }, { name: "job", slice: "M00000002" }, - { name: "notes", slice: "M00000005", textAlign: "center" }, + { + name: "notes", + slice: "M00000005", + textAlignment: TextAlignment.Center, + }, ], showColumnHeaders: true, }); diff --git a/packages/@atjson/renderer-html/test/tiktok-embed.test.ts b/packages/@atjson/renderer-html/test/tiktok-embed.test.ts new file mode 100644 index 000000000..c40c5c19e --- /dev/null +++ b/packages/@atjson/renderer-html/test/tiktok-embed.test.ts @@ -0,0 +1,26 @@ +import OffsetSource, { TikTokEmbed } from "@atjson/offset-annotations"; +import { ParseAnnotation } from "@atjson/document"; +import Renderer from "../src"; + +test("TiktokEmbed", () => { + let doc = new OffsetSource({ + content: "\uFFFC", + annotations: [ + new TikTokEmbed({ + start: 0, + end: 1, + attributes: { + url: "https://www.tiktok.com/@vogueitalia/video/6771026615137750277", + }, + }), + new ParseAnnotation({ + start: 0, + end: 1, + }), + ], + }); + + expect(Renderer.render(doc)).toEqual( + `
@vogueitalia
` + ); +}); diff --git a/packages/@atjson/renderer-react/test/react-renderer.test.tsx b/packages/@atjson/renderer-react/test/react-renderer.test.tsx index ebab4321d..63ccc26b1 100644 --- a/packages/@atjson/renderer-react/test/react-renderer.test.tsx +++ b/packages/@atjson/renderer-react/test/react-renderer.test.tsx @@ -379,102 +379,4 @@ describe("ReactRenderer", () => { ); }); }); - - describe("Subdocuments", () => { - it("renders single-level nested subdocuments", () => { - const subDoc = new CaptionSource({ - content: "This is some caption text", - annotations: [ - new Bold({ - start: 0, - end: 4, - }), - new Italic({ - start: 8, - end: 12, - }), - ], - }); - - let doc = new OffsetSource({ - content: "An embed with caption () and some text following.", - annotations: [ - new Bold({ - start: 3, - end: 8, - }), - new IframeEmbedWithSubdocument({ - start: 23, - end: 24, - attributes: { - url: "https://foo.bar", - caption: subDoc, - }, - }), - new ParseAnnotation({ - start: 23, - end: 24, - }), - ], - }); - - expect( - renderDocument(doc, { - Bold: BoldComponent, - Italic: ItalicComponent, - IframeEmbedWithSubdocument: IframeComponent, - }) - ).toBe( - `An embed with caption (
This is some caption text
) and some text following.` - ); - }); - - it("Accepts alternate components via a provider", () => { - const subDoc = new CaptionSource({ - content: "This is some caption text", - annotations: [ - new Bold({ - start: 0, - end: 4, - }), - new Italic({ - start: 8, - end: 12, - }), - ], - }); - - let doc = new OffsetSource({ - content: "An embed with caption () and some text following.", - annotations: [ - new Bold({ - start: 3, - end: 8, - }), - new IframeEmbedWithSubdocument({ - start: 23, - end: 24, - attributes: { - url: "https://foo.bar", - caption: subDoc, - }, - }), - new ParseAnnotation({ - start: 23, - end: 24, - }), - ], - }); - - expect( - renderDocument(doc, { - Bold: BoldComponent, - Italic: ItalicComponent, - IframeEmbedWithSubdocument: IframeComponentWithProvider, - }) - ).toBe( - `An embed with caption (
This is some caption text
) and some text following.` - ); - }); - }); }); diff --git a/packages/@atjson/source-commonmark/test/__snapshots__/extensions.test.ts.snap b/packages/@atjson/source-commonmark/test/__snapshots__/extensions.test.ts.snap index c3898f247..dcfb611f4 100644 --- a/packages/@atjson/source-commonmark/test/__snapshots__/extensions.test.ts.snap +++ b/packages/@atjson/source-commonmark/test/__snapshots__/extensions.test.ts.snap @@ -9,12 +9,12 @@ exports[`tables adjacent tables 1`] = ` { "name": "name", "slice": "M00000000", - "textAlign": "left", + "textAlignment": "start", }, { "name": "age", "slice": "M00000001", - "textAlign": "right", + "textAlignment": "end", }, { "name": "job", @@ -23,7 +23,7 @@ exports[`tables adjacent tables 1`] = ` { "name": "notes", "slice": "M00000003", - "textAlign": "center", + "textAlignment": "center", }, ], "dataSet": "B00000001", @@ -330,12 +330,12 @@ exports[`tables adjacent tables 1`] = ` { "name": "name", "slice": "M00000019", - "textAlign": "left", + "textAlignment": "start", }, { "name": "age", "slice": "M0000001a", - "textAlign": "right", + "textAlignment": "end", }, { "name": "job", @@ -344,7 +344,7 @@ exports[`tables adjacent tables 1`] = ` { "name": "notes", "slice": "M0000001c", - "textAlign": "center", + "textAlignment": "center", }, ], "dataSet": "B00000017", @@ -1125,12 +1125,12 @@ exports[`tables converting 1`] = ` { "name": "name", "slice": "M00000000", - "textAlign": "left", + "textAlignment": "start", }, { "name": "age", "slice": "M00000001", - "textAlign": "right", + "textAlignment": "end", }, { "name": "job", @@ -1139,7 +1139,7 @@ exports[`tables converting 1`] = ` { "name": "notes", "slice": "M00000003", - "textAlign": "center", + "textAlignment": "center", }, ], "dataSet": "B00000001", diff --git a/packages/@atjson/source-gdocs-paste/src/converter.ts b/packages/@atjson/source-gdocs-paste/src/converter.ts index a290dfe16..8a725975f 100644 --- a/packages/@atjson/source-gdocs-paste/src/converter.ts +++ b/packages/@atjson/source-gdocs-paste/src/converter.ts @@ -17,9 +17,10 @@ import OffsetSource, { DataSet, ColumnType, Table, + TextAlignment, } from "@atjson/offset-annotations"; import GDocsSource from "./source"; -import { Heading as GDocsHeading } from "./annotations"; +import { Alignment, Heading as GDocsHeading } from "./annotations"; import uuid from "uuid-random"; // eslint-disable-next-line no-control-regex @@ -34,9 +35,9 @@ const NEWLINE_PARAGRAPH_SEPARATOR = /\n(\s*\n)*/g; const ALIGNMENT = { 0: undefined, - 1: "center", - 2: "end", - 3: "justify", + 1: TextAlignment.Center, + 2: TextAlignment.End, + 3: TextAlignment.Justify, } as const; function snakecase(text: string) { @@ -98,7 +99,7 @@ GDocsSource.defineConverterTo(OffsetSource, (doc) => { end: heading.end, attributes: { level: level as 1 | 2 | 3 | 4 | 5 | 6, - alignment: ALIGNMENT[heading.attributes.align], + textAlignment: ALIGNMENT[heading.attributes.align], }, }) ); @@ -224,29 +225,14 @@ GDocsSource.defineConverterTo(OffsetSource, (doc) => { } }); - doc.where({ type: "-gdocs-ps_al" }).update((align) => { - let alignment: "start" | "center" | "end" | "justify" | undefined; - switch (align.attributes.align) { - case 0: - alignment = "start"; - break; - case 1: - alignment = "center"; - break; - case 2: - alignment = "end"; - break; - case 3: - alignment = "justify"; - break; - } + doc.where({ type: "-gdocs-ps_al" }).update((align: Alignment) => { doc.replaceAnnotation( align, new Paragraph({ start: align.start, end: align.end, attributes: { - alignment, + textAlignment: ALIGNMENT[align.attributes.align], }, }) ); diff --git a/packages/@atjson/source-gdocs-paste/test/text-alignment.test.ts b/packages/@atjson/source-gdocs-paste/test/text-alignment.test.ts index 7efb915bf..039225090 100644 --- a/packages/@atjson/source-gdocs-paste/test/text-alignment.test.ts +++ b/packages/@atjson/source-gdocs-paste/test/text-alignment.test.ts @@ -1,4 +1,4 @@ -import OffsetSource from "@atjson/offset-annotations"; +import OffsetSource, { TextAlignment } from "@atjson/offset-annotations"; import * as fs from "fs"; import * as path from "path"; import GDocsSource from "../src"; @@ -51,7 +51,10 @@ describe("@atjson/source-gdocs-paste", () => { type: "-offset-heading", start: 5, end: 13, - attributes: { "-offset-level": 2, "-offset-alignment": "center" }, + attributes: { + "-offset-level": 2, + "-offset-textAlignment": TextAlignment.Center, + }, }, ]); }); @@ -69,7 +72,10 @@ describe("@atjson/source-gdocs-paste", () => { type: "-offset-heading", start: 14, end: 19, - attributes: { "-offset-level": 3, "-offset-alignment": "end" }, + attributes: { + "-offset-level": 3, + "-offset-textAlignment": TextAlignment.End, + }, }, ]); }); @@ -87,7 +93,10 @@ describe("@atjson/source-gdocs-paste", () => { type: "-offset-heading", start: 20, end: 29, - attributes: { "-offset-level": 4, "-offset-alignment": "justify" }, + attributes: { + "-offset-level": 4, + "-offset-textAlignment": TextAlignment.Justify, + }, }, ]); }); @@ -126,7 +135,7 @@ describe("@atjson/source-gdocs-paste", () => { type: "-offset-paragraph", start: 5, end: 13, - attributes: { "-offset-alignment": "center" }, + attributes: { "-offset-textAlignment": TextAlignment.Center }, }); }); @@ -136,7 +145,7 @@ describe("@atjson/source-gdocs-paste", () => { type: "-offset-paragraph", start: 14, end: 19, - attributes: { "-offset-alignment": "end" }, + attributes: { "-offset-textAlignment": TextAlignment.End }, }); }); @@ -146,7 +155,7 @@ describe("@atjson/source-gdocs-paste", () => { type: "-offset-paragraph", start: 20, end: 29, - attributes: { "-offset-alignment": "justify" }, + attributes: { "-offset-textAlignment": TextAlignment.Justify }, }); }); }); @@ -183,7 +192,7 @@ describe("@atjson/source-gdocs-paste", () => { type: "-offset-paragraph", start: 6, end: 10, - attributes: { "-offset-alignment": "center" }, + attributes: { "-offset-textAlignment": TextAlignment.Center }, }); }); @@ -193,7 +202,7 @@ describe("@atjson/source-gdocs-paste", () => { type: "-offset-paragraph", start: 11, end: 18, - attributes: { "-offset-alignment": "end" }, + attributes: { "-offset-textAlignment": TextAlignment.End }, }); }); @@ -203,7 +212,7 @@ describe("@atjson/source-gdocs-paste", () => { type: "-offset-paragraph", start: 19, end: 21, - attributes: { "-offset-alignment": "justify" }, + attributes: { "-offset-textAlignment": TextAlignment.Justify }, }); }); }); diff --git a/packages/@atjson/source-html/src/converter/headings.ts b/packages/@atjson/source-html/src/converter/headings.ts index 2750223d1..f3cb06c3a 100644 --- a/packages/@atjson/source-html/src/converter/headings.ts +++ b/packages/@atjson/source-html/src/converter/headings.ts @@ -1,6 +1,6 @@ import Document, { is, AnnotationConstructor } from "@atjson/document"; import { Heading } from "@atjson/offset-annotations"; -import { parseCSS, toAlignment } from "./utils"; +import { parseCSS, toTextAlignment } from "./utils"; import { H1, H2, H3, H4, H5, H6 } from "../annotations"; function convert( @@ -27,7 +27,7 @@ function convert( "Right to left languages are currently not supported in atjson." ); } - let alignment = toAlignment( + let textAlignment = toTextAlignment( parseCSS(heading.attributes.style)["text-align"], direction?.attributes?.dir ); @@ -41,7 +41,7 @@ function convert( attributes: { anchorName: heading.attributes.id, level, - alignment, + textAlignment, }, }) ); diff --git a/packages/@atjson/source-html/src/converter/paragraphs.ts b/packages/@atjson/source-html/src/converter/paragraphs.ts index f355557fe..b8fe1d91c 100644 --- a/packages/@atjson/source-html/src/converter/paragraphs.ts +++ b/packages/@atjson/source-html/src/converter/paragraphs.ts @@ -1,6 +1,6 @@ import Document from "@atjson/document"; import { Paragraph } from "@atjson/offset-annotations"; -import { parseCSS, toAlignment } from "./utils"; +import { parseCSS, toTextAlignment } from "./utils"; export default function (doc: Document) { doc @@ -30,7 +30,7 @@ export default function (doc: Document) { end: paragraph.end, attributes: { anchorName: paragraph.attributes.id, - alignment: toAlignment( + textAlignment: toTextAlignment( parseCSS(paragraph.attributes.style)["text-align"], direction?.attributes?.lang ), diff --git a/packages/@atjson/source-html/src/converter/social-embeds.ts b/packages/@atjson/source-html/src/converter/social-embeds.ts index 190a869d5..f98c87c17 100644 --- a/packages/@atjson/source-html/src/converter/social-embeds.ts +++ b/packages/@atjson/source-html/src/converter/social-embeds.ts @@ -77,7 +77,8 @@ export default function (doc: Document) { (!src || src.includes("instagram.com") || src.includes("twitter.com") || - src.includes("tiktok.com")) + src.includes("tiktok.com") || + src.includes("x.com")) ); } ) diff --git a/packages/@atjson/source-html/src/converter/utils.ts b/packages/@atjson/source-html/src/converter/utils.ts index 6cef561cc..ef90c8a0c 100644 --- a/packages/@atjson/source-html/src/converter/utils.ts +++ b/packages/@atjson/source-html/src/converter/utils.ts @@ -1,3 +1,5 @@ +import { TextAlignment } from "@atjson/offset-annotations"; + export function parseCSS(css: string | undefined) { let rules = (css || "").split(";"); let styles: Record = {}; @@ -11,25 +13,29 @@ export function parseCSS(css: string | undefined) { } const RightToLeftAlignment = { - left: "end", - right: "start", - center: "center", - justify: "justify", -} as { [key: string]: "start" | "end" | "center" | "justify" | undefined }; + start: TextAlignment.Start, + left: TextAlignment.End, + right: TextAlignment.Start, + end: TextAlignment.End, + center: TextAlignment.Center, + justify: TextAlignment.Justify, +} as { [key: string]: TextAlignment | undefined }; const LeftToRightAlignment = { - left: "start", - right: "end", - center: "center", - justify: "justify", -} as { [key: string]: "start" | "end" | "center" | "justify" | undefined }; + start: TextAlignment.Start, + left: TextAlignment.Start, + right: TextAlignment.End, + end: TextAlignment.End, + center: TextAlignment.Center, + justify: TextAlignment.Justify, +} as { [key: string]: TextAlignment | undefined }; /** * * @param alignment The `text-align` property of the * @param language The language code of */ -export function toAlignment( +export function toTextAlignment( alignment: string | undefined, direction: string | undefined ) { diff --git a/packages/@atjson/source-html/test/__snapshots__/table.test.ts.snap b/packages/@atjson/source-html/test/__snapshots__/table.test.ts.snap index 10c6736f6..e9d341d2f 100644 --- a/packages/@atjson/source-html/test/__snapshots__/table.test.ts.snap +++ b/packages/@atjson/source-html/test/__snapshots__/table.test.ts.snap @@ -646,7 +646,7 @@ exports[`tables valid tables converts column alignments 1`] = ` { "name": "name", "slice": "M00000000", - "textAlign": "left", + "textAlignment": "start", }, { "name": "age", @@ -659,7 +659,7 @@ exports[`tables valid tables converts column alignments 1`] = ` { "name": "notes", "slice": "M00000003", - "textAlign": "right", + "textAlignment": "end", }, ], "dataSet": "B00000002", diff --git a/packages/@atjson/source-html/test/heading.test.ts b/packages/@atjson/source-html/test/heading.test.ts index 5d199b89c..611de9ff4 100644 --- a/packages/@atjson/source-html/test/heading.test.ts +++ b/packages/@atjson/source-html/test/heading.test.ts @@ -1,4 +1,4 @@ -import OffsetSource from "@atjson/offset-annotations"; +import OffsetSource, { TextAlignment } from "@atjson/offset-annotations"; import HTMLSource from "../src"; describe("headings", () => { @@ -25,11 +25,13 @@ describe("headings", () => { ["without direction attribute", ""], ])("%s", (dir) => { describe.each([ - ["left", "start"], - ["center", "center"], - ["right", "end"], - ["justify", "justify"], - ] as const)("%s", (textAlign, alignment) => { + ["left", TextAlignment.Start], + ["start", TextAlignment.Start], + ["center", TextAlignment.Center], + ["right", TextAlignment.End], + ["end", TextAlignment.End], + ["justify", TextAlignment.Justify], + ] as const)("%s", (textAlign, textAlignment) => { test.each([["h1"], ["h2"], ["h3"], ["h4"], ["h5"], ["h6"]])( "%s", (tagname) => { @@ -38,7 +40,7 @@ describe("headings", () => { ).convertTo(OffsetSource); expect( doc.where({ type: `-offset-heading` }).annotations - ).toMatchObject([{ attributes: { alignment } }]); + ).toMatchObject([{ attributes: { textAlignment } }]); } ); }); @@ -47,10 +49,12 @@ describe("headings", () => { describe("right to left", () => { describe.each([ - ["left", "end"], - ["center", "center"], - ["right", "start"], - ["justify", "justify"], + ["left", TextAlignment.End], + ["start", TextAlignment.Start], + ["center", TextAlignment.Center], + ["right", TextAlignment.Start], + ["end", TextAlignment.End], + ["justify", TextAlignment.Justify], ] as const)("%s", (textAlign) => { test.each([["h1"], ["h2"], ["h3"], ["h4"], ["h5"], ["h6"]])( "%s", diff --git a/packages/@atjson/source-html/test/paragraph.test.ts b/packages/@atjson/source-html/test/paragraph.test.ts index d9adea091..ee42f0f1c 100644 --- a/packages/@atjson/source-html/test/paragraph.test.ts +++ b/packages/@atjson/source-html/test/paragraph.test.ts @@ -1,4 +1,4 @@ -import OffsetSource from "@atjson/offset-annotations"; +import OffsetSource, { TextAlignment } from "@atjson/offset-annotations"; import HTMLSource from "../src"; describe("paragraphs", () => { @@ -9,11 +9,11 @@ describe("paragraphs", () => { ["without direction attribute", ""], ])("%s", (dir) => { test.each([ - ["left", "start"], - ["right", "end"], - ["center", "center"], - ["justify", "justify"], - ] as const)("%s attribute is converted", (textAlign, alignment) => { + ["left", TextAlignment.Start], + ["right", TextAlignment.End], + ["center", TextAlignment.Center], + ["justify", TextAlignment.Justify], + ] as const)("%s attribute is converted", (textAlign, textAlignment) => { let doc = HTMLSource.fromRaw( `

Here is some text

` ).convertTo(OffsetSource); @@ -23,7 +23,7 @@ describe("paragraphs", () => { ).toMatchObject([ { attributes: { - alignment, + textAlignment, }, }, ]); @@ -33,10 +33,10 @@ describe("paragraphs", () => { describe("right to left", () => { test.each([ - ["left", "end"], - ["right", "start"], - ["center", "center"], - ["justify", "justify"], + ["left", TextAlignment.End], + ["right", TextAlignment.Start], + ["center", TextAlignment.Center], + ["justify", TextAlignment.Justify], ] as const)("%s attribute is converted", (textAlign) => { expect(() => { HTMLSource.fromRaw(