{"version":3,"sources":["webpack://@lemon8/web-seo/./shared/models/#common/user-type.ts","webpack://@lemon8/web-seo/./shared/models/article/article-unavailable.ts","webpack://@lemon8/web-seo/./shared/models/article/json-ld-util.ts","webpack://@lemon8/web-seo/./shared/models/article/article-util.ts","webpack://@lemon8/web-seo/./shared/models/article/article.ts","webpack://@lemon8/web-seo/./shared/models/comments/json-ld-util.ts","webpack://@lemon8/web-seo/./shared/models/comments/comment.ts","webpack://@lemon8/web-seo/./shared/models/comments/rich-content.ts","webpack://@lemon8/web-seo/./shared/models/discover/discover-data.ts","webpack://@lemon8/web-seo/./shared/models/discover/discover-util.ts","webpack://@lemon8/web-seo/./shared/models/experience/types.ts","webpack://@lemon8/web-seo/./shared/models/experience/json-ld-util.ts","webpack://@lemon8/web-seo/./shared/models/experience/experience-util.ts","webpack://@lemon8/web-seo/./shared/models/legacy/article.ts","webpack://@lemon8/web-seo/./shared/models/legacy/category.ts","webpack://@lemon8/web-seo/./shared/models/legacy/topic.ts","webpack://@lemon8/web-seo/./shared/models/legacy/user.ts","webpack://@lemon8/web-seo/./shared/models/media.ts","webpack://@lemon8/web-seo/./shared/models/page-level-traffic.ts","webpack://@lemon8/web-seo/./shared/models/search-word.ts","webpack://@lemon8/web-seo/./shared/models/search/sug.ts","webpack://@lemon8/web-seo/./shared/models/topic/topic-unavailable.ts","webpack://@lemon8/web-seo/./shared/models/topic/topic-util.ts","webpack://@lemon8/web-seo/./shared/models/user/types.ts","webpack://@lemon8/web-seo/./shared/models/user/user-unavailable.ts","webpack://@lemon8/web-seo/./shared/models/user/json-ld-util.ts","webpack://@lemon8/web-seo/./shared/models/user/user.ts","webpack://@lemon8/web-seo/./shared/utils/escape-xml.ts","webpack://@lemon8/web-seo/./shared/utils/format/time-formatter.ts"],"names":["EUserType","UserTypeUtil","getLinkNamePrefix","type","includes","getLinkNamePrefixByBelongTT","belongTT","EArticleUnavailableReason","SEOPostBanReasonMap","EPostSeoBanStatus","ArticleJsonLDUtil","getTitle","props","article","t","articleTitle","title","removeEscapedSpecialXmlCharacter","replace","articleClass","EArticleClass","concat","author","nickName","getDescription","articleShortContent","shortContent","getKeywords","result","push","getSocialMediaJsonLD","region","articleTranslated","ArticleDetailUtil","jsonLDTitle","jsonLDDescription","jsonLDKeywords","canonicalUrl","articleRegion","readCount","diggCount","favoriteCount","commentCount","publishTime","modifyTime","gptSummary","imageList","galleryImageList","galleryLabels","ocrText","imageListWithExtraInfo","map","image","index","_objectSpread","imgOcrText","galleryKeywords","filter","label","imageIndex","name","url","contentUrl","representativeOfPage","keywords","caption","String","embeddedTextCaption","largeImage","articleBaseJsonLD","headline","description","datePublished","dateToLocalISO","sharedContent","mainEntityOfPage","interactionStatistic","interactionType","userInteractionCount","dateModified","abstract","getVideoObjectJsonLD","_a","video","isTranslatedVersion","output","thumbnailUrl","uploadDate","encryptedUrl","width","height","duration","VideoUtils","ocr","length","join","isArticleAvailable","hasTranslatedVersion","translatedRegions","isTranslatedArticleToShow","_region","getArticlePath","userType","linkName","groupId","getArticleHref","translatedRegion","getAuthorPath","getAuthorHref","getCoverImage","JsonLD","ECommentPermission","EWarningLabelType","CommentJsonLDUtil","getCommentsJsonLd","comments","item","text","alternateName","avatar","identifier","propertyID","value","CommentUtil","isReply","comment","replyToCommentId","isPrimaryComment","isReplyToReply","replyToReplyId","prefix","JsonLd","CommentRichContentUtil","ECommentRichContentCategory","EDiscoverUnavailableReason","DiscoverUtil","Libra","shouldUseSortModel","parameters","Boolean","_get","shouldFormatAsArticleDetail","isDiscoverDataAvailable","input","EExperienceUnavailableReason","ExperienceJsonLDUtil","experience","question","publishYear","Date","submitTimeStamp","getFullYear","toString","answerContent","isNewType","content","getArticleJsonLD","articleInfoList","imgCaptions","forEach","articleLikes","ocrTextArr","imgCaption","getPersonJsonLD","user","userRegion","person","UserDetailUtil","followerCount","Number","publishCount","ExperienceUtil","isExperienceDataAvailable","LegacyArticleUtil","path","ECategoryNameIDMap","CategoryIDNameMap","CategoryNameIDMap","Object","keys","reduce","pre","cur","LegacyTopicArticleUtil","authorType","LegacyUserUtil","getPath","EVideoMuteStatus","durationTo8601","hour","Math","trunc","minute","second","ret","PageLevelTrafficUtil","getPageIdFromTraffic","traffic","pageType","EPageType","categoryId","hashtagId","poiId","keyword","userId","EWordType","SugType","ETopicUnavailableReason","TopicUtil","isTopicAvailable","topic","PrivacyStatus","EUserUnavailableReason","SEOBanReasonMap","ESeoBanStatus","UserJsonLDUtil","dugCount","favoredCount","postCount","EUserGender","EPrivacyStatus","isUserAvailable","escapeSpecialXmlCharacter","unescapeSpecialXmlCharacter","timeStamp","timeZone","off","absoff","abs","toISOString","substr","toFixed","padStart","getTodayAndMondayDate","today","dayOfWeek","getDay","monday","daysSinceMonday","setDate","getDate","formatDate","date","useSlashFormat","year","month","getMonth","day","todayInSlashFormat","mondayInSlashFormat"],"mappings":"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","file":"vendors/156-aba18b4a3c588f998a0f-ade4ba9718be3d0b2f6b26782fbeda8b1ed36057.js","sourcesContent":["export enum EUserType {\n Unknown = 0,\n LemonLegacyUser = 1,\n LemonUpgradedUser = 2,\n TTUser = 3,\n}\n\nexport const UserTypeUtil = {\n getLinkNamePrefix: (type: EUserType): '' | '@' =>\n [EUserType.Unknown, EUserType.LemonLegacyUser].includes(type) ? '' : '@',\n getLinkNamePrefixByBelongTT: (belongTT: boolean): '' | '@' => {\n return belongTT ? '@' : '';\n },\n};\n","import { EPostSeoBanStatus } from '.';\n\nexport enum EArticleUnavailableReason {\n NOT_FOUND = 'not_found',\n PRIVATE_ACCOUNT = 'private_account',\n UNDER_AGE_ACCOUNT = 'under_age',\n ERR_VISIBILITY = 'err_visibility_level',\n ERR_PERMISSION = 'err_permission',\n SEO_BAN_UNKNOWN = 'seo_ban_unknown',\n SERVER_ERROR = 'server_error',\n}\n\nexport const SEOPostBanReasonMap: Record = {\n [EPostSeoBanStatus.Unknown]: EArticleUnavailableReason.SEO_BAN_UNKNOWN,\n [EPostSeoBanStatus.PrivateAuthor]: EArticleUnavailableReason.PRIVATE_ACCOUNT,\n [EPostSeoBanStatus.AuthorUnderAge]: EArticleUnavailableReason.UNDER_AGE_ACCOUNT,\n [EPostSeoBanStatus.ErrVisibility]: EArticleUnavailableReason.ERR_VISIBILITY,\n [EPostSeoBanStatus.ErrPermission]: EArticleUnavailableReason.ERR_PERMISSION,\n};\n\nexport interface IArticleUnavailableDetail {\n groupId: string;\n unavailableReason: EArticleUnavailableReason;\n}\n","import {\n ArticleDetailUtil,\n EArticleClass,\n TArticleDetail,\n IGalleryArticleDetail,\n IImage,\n IRichArticleDetail,\n IVideoArticleDetail,\n VideoUtils,\n} from 'shared/models';\nimport { ImageObject, SocialMediaPosting, VideoObject } from 'schema-dts';\nimport { Region } from '@lemon8/web-app-shared/i18n';\nimport type { TFunction } from 'i18next';\nimport { removeEscapedSpecialXmlCharacter } from 'shared/utils/escape-xml';\nimport { dateToLocalISO } from 'shared/utils/format/time-formatter';\n\nexport const ArticleJsonLDUtil = {\n getTitle: (props: { article: TArticleDetail; region: Region; t: TFunction }): string => {\n const { article, t } = props;\n\n const articleTitle = article.title;\n if (articleTitle) {\n return removeEscapedSpecialXmlCharacter(articleTitle.replace(/\\s+/g, ' '));\n }\n\n // 3. fallback title according to article class\n if (article.articleClass === EArticleClass.GALLERY) {\n return `${t('user_published_gallery').replace('%s', article.author.nickName)} | Lemon8`;\n } else if (article.articleClass === EArticleClass.VIDEO) {\n return `${t('own_video').replace('%s', article.author.nickName)} | Lemon8`;\n } else {\n return `${t('user_published_article').replace('%s', article.author.nickName)} | Lemon8`;\n }\n },\n getDescription: (props: { article: TArticleDetail; region: Region; t: TFunction }): string => {\n const { article } = props;\n\n const articleShortContent = article.shortContent;\n if (articleShortContent) {\n return removeEscapedSpecialXmlCharacter(articleShortContent.replace(/\\s+/g, ' '));\n }\n return ArticleJsonLDUtil.getTitle(props);\n },\n getKeywords: (props: { article: TArticleDetail; region: Region; t: TFunction }): string[] => {\n const { article } = props;\n\n const result: string[] = [];\n // const { relatedQueryInfos } = article;\n\n const articleTitle = article.title;\n if (articleTitle) {\n result.push(articleTitle);\n }\n\n result.push(article.author.nickName);\n // result.push(...relatedQueryInfos.map((info) => info.word));\n result.push('Lemon8');\n return result;\n },\n getSocialMediaJsonLD: (props: {\n article: TArticleDetail;\n region: Region;\n t: TFunction;\n abInfo: Record;\n }): SocialMediaPosting => {\n // region: page on the URL query\n const { article, region, t } = props;\n const articleTranslated = ArticleDetailUtil.isTranslatedArticleToShow(article, region);\n\n const jsonLDTitle = ArticleJsonLDUtil.getTitle(props);\n const jsonLDDescription = ArticleJsonLDUtil.getDescription(props);\n const jsonLDKeywords = ArticleJsonLDUtil.getKeywords(props);\n const canonicalUrl = `https://www.lemon8-app.com${ArticleDetailUtil.getArticlePath(article)}?region=${\n articleTranslated ? region : article.articleRegion\n }`;\n\n const articleTitle = article.title;\n\n const { readCount, diggCount, favoriteCount, commentCount, publishTime, modifyTime, gptSummary } = article;\n\n const imageList: ImageObject[] = [];\n\n if (article.articleClass === EArticleClass.GALLERY) {\n const { imageList: galleryImageList, galleryLabels, ocrText = [] } = article as IGalleryArticleDetail;\n\n const imageListWithExtraInfo = galleryImageList.map((image, index) => {\n return {\n ...image,\n imgOcrText: ocrText[index] || '',\n };\n });\n\n imageList.push(\n ...imageListWithExtraInfo.map((image: IImage & { imgOcrText: string }, index: number): ImageObject => {\n const galleryKeywords = galleryLabels\n .filter((label) => label.imageIndex === index)\n .map((label) => label.name);\n\n return {\n '@type': 'ImageObject',\n url: image.url,\n contentUrl: image.url,\n representativeOfPage: 'True',\n keywords: [...galleryKeywords, articleTitle, article.author.nickName, 'Lemon8'],\n caption: t('own_picture_with_count')\n .replace('%s', articleTitle)\n .replace('%d', String(index + 1)),\n embeddedTextCaption: !articleTranslated ? image.imgOcrText || '' : '',\n };\n }),\n );\n } else {\n const { largeImage } = article as IVideoArticleDetail | IRichArticleDetail;\n imageList.push({\n '@type': 'ImageObject',\n url: largeImage.url,\n contentUrl: largeImage.url,\n representativeOfPage: 'True',\n keywords: [articleTitle, article.author.nickName, 'Lemon8'],\n caption: t('own_picture_with_count').replace('%s', articleTitle).replace('%d', '1'),\n } as ImageObject);\n }\n\n const articleBaseJsonLD: SocialMediaPosting = {\n '@type': 'SocialMediaPosting',\n headline: jsonLDTitle,\n description: jsonLDDescription,\n keywords: jsonLDKeywords,\n url: canonicalUrl,\n commentCount,\n\n datePublished: dateToLocalISO(publishTime, /** currently fix timezone to JP. @lidiang */ 9),\n\n image: imageList,\n sharedContent: imageList,\n\n mainEntityOfPage: {\n '@id': canonicalUrl,\n '@type': 'WebPage',\n },\n interactionStatistic: [\n {\n '@type': 'InteractionCounter',\n interactionType: {\n '@type': 'ViewAction',\n },\n userInteractionCount: readCount,\n },\n {\n '@type': 'InteractionCounter',\n interactionType: {\n '@type': 'LikeAction',\n },\n userInteractionCount: diggCount,\n },\n {\n '@type': 'InteractionCounter',\n interactionType: {\n '@type': 'BookmarkAction',\n },\n userInteractionCount: favoriteCount,\n },\n ],\n };\n\n if (modifyTime) {\n articleBaseJsonLD.dateModified = dateToLocalISO(modifyTime, /** currently fix timezone to JP. @lidiang */ 9);\n }\n\n if (gptSummary) {\n articleBaseJsonLD.abstract = gptSummary;\n }\n\n return articleBaseJsonLD;\n },\n getVideoObjectJsonLD: (props: {\n article: IVideoArticleDetail;\n region: Region;\n t: TFunction;\n abInfo: Record;\n }): VideoObject => {\n const { article } = props;\n const {\n video,\n readCount,\n diggCount,\n favoriteCount,\n largeImage,\n publishTime,\n gptSummary,\n isTranslatedVersion = false,\n } = article;\n\n const title = ArticleJsonLDUtil.getTitle(props);\n const description = ArticleJsonLDUtil.getTitle(props);\n\n const output: VideoObject = {\n '@type': 'VideoObject',\n name: title,\n description,\n thumbnailUrl: largeImage.url,\n uploadDate: dateToLocalISO(publishTime, /** currently fix timezone to JP. @lidiang */ 9),\n contentUrl: video.encryptedUrl || video.url,\n width: `${article.video.width}`,\n height: `${article.video.height}`,\n interactionStatistic: [\n {\n '@type': 'InteractionCounter',\n interactionType: {\n '@type': 'WatchAction',\n },\n userInteractionCount: readCount,\n },\n {\n '@type': 'InteractionCounter',\n interactionType: {\n '@type': 'LikeAction',\n },\n userInteractionCount: diggCount,\n },\n {\n '@type': 'InteractionCounter',\n interactionType: {\n '@type': 'BookmarkAction',\n },\n userInteractionCount: favoriteCount,\n },\n ],\n };\n\n if (article.video.duration) {\n output.duration = VideoUtils.durationTo8601(article.video.duration);\n }\n\n if (gptSummary) {\n output.abstract = gptSummary;\n }\n\n if (video.ocr?.length && !isTranslatedVersion) {\n output.embeddedTextCaption = video.ocr.join(', ');\n }\n\n return output;\n },\n};\n","import { EArticleClass, IGalleryArticleDetail, TArticleDetail } from 'shared/models/article/article';\nimport { Region } from '@lemon8/web-app-shared/i18n';\nimport { IArticleUnavailableDetail } from './article-unavailable';\nimport { ArticleJsonLDUtil } from 'shared/models/article/json-ld-util';\nimport { UserTypeUtil } from '../#common';\nimport { Article, IImage } from '..';\n\nexport const ArticleDetailUtil = {\n isArticleAvailable: (article: IArticleUnavailableDetail | TArticleDetail): article is TArticleDetail => {\n return !('unavailableReason' in article);\n },\n /**\n * article has translated version\n */\n hasTranslatedVersion: (article: TArticleDetail): boolean => {\n const { translatedRegions = [] } = article;\n return translatedRegions.length !== 0;\n },\n /**\n * article is translated, and translated version is needed to show\n */\n isTranslatedArticleToShow: (article: TArticleDetail, _region: Region): boolean => {\n const { isTranslatedVersion = false } = article;\n return isTranslatedVersion;\n },\n\n getArticlePath: (article: TArticleDetail): string => {\n return `/${UserTypeUtil.getLinkNamePrefix(article.author.userType)}${article.author.linkName}/${article.groupId}`;\n },\n\n getArticleHref: (article: TArticleDetail, translatedRegion?: Region): string => {\n return `${ArticleDetailUtil.getArticlePath(article)}?region=${translatedRegion || article.articleRegion}`;\n },\n\n getAuthorPath: (article: TArticleDetail): string => {\n return `/${UserTypeUtil.getLinkNamePrefix(article.author.userType)}${article.author.linkName}`;\n },\n\n getAuthorHref: (article: TArticleDetail, translatedRegion?: Region): string => {\n return `/${UserTypeUtil.getLinkNamePrefix(article.author.userType)}${article.author.linkName}?region=${\n translatedRegion || article.articleRegion\n }`;\n },\n\n getCoverImage: (article: TArticleDetail | Article): IImage => {\n switch (article.articleClass) {\n case EArticleClass.GALLERY:\n return (article as IGalleryArticleDetail).imageList[0];\n case EArticleClass.ARTICLE:\n case EArticleClass.VIDEO:\n default:\n return article.largeImage;\n }\n },\n\n JsonLD: ArticleJsonLDUtil,\n};\n","import { EUserType } from 'shared/models';\nimport { IImage, IVideo } from '../media';\nimport { IUserAuthInfo } from 'shared/models/user-auth-info';\nimport { Region } from '@lemon8/web-app-shared/i18n';\n\nexport enum EPostSeoBanStatus {\n Unknown = 0,\n PrivateAuthor = 1,\n AuthorUnderAge = 2,\n ErrVisibility = 3,\n ErrPermission = 4,\n}\n\nexport enum ECommentPermission {\n All = 0, // 显示评论区\n Follower = 1, // 粉丝可评论\n Self = 2, // 自己可评论\n Disable = 3, // 不可评论,不显示评论区\n Friend = 4, // 好友可评论\n}\n\nexport interface GalleryLabelType {\n direction: string;\n id: string;\n imageIndex: number;\n name: string;\n type: string;\n xPct: number;\n yPct: number;\n}\n\nexport enum EArticleClass {\n GALLERY = 'Gallery',\n VIDEO = 'Video',\n ARTICLE = 'Article',\n}\n\nexport enum EWarningLabelType {\n DANGER = 101,\n DANGER_PROFESSIONAL = 102,\n COSMETIC_SURGERY = 103,\n SHOCKING = 401,\n ELECTION = 10001,\n}\n\nexport interface IIllegalInfo {\n warningLabel: string;\n warningLabelType: EWarningLabelType;\n}\n\nexport interface IArticleDetail {\n groupId: string;\n templateId?: string;\n imprId?: string;\n\n // author\n author: {\n userId: string;\n avatar: string;\n authInfo: IUserAuthInfo;\n nickName: string;\n linkName: string;\n followerCount: number;\n userType: EUserType;\n };\n\n // content\n articleClass: EArticleClass;\n\n // TODO cast to i18n:Region\n articleRegion: Region;\n title: string;\n content: string;\n shortContent: string;\n\n translatedRegions?: string[];\n isTranslatedVersion?: boolean;\n\n gptSummary?: string;\n\n // content publish time\n publishTime: number;\n modifyTime?: number;\n\n // interaction\n readCount: number;\n diggCount: number;\n favoriteCount: number;\n commentCount: number;\n\n // legacy hashtag\n forumList?: {\n id: string;\n name: string;\n }[];\n\n // poi\n locationInfo?: {\n poiId: string;\n poiName: string;\n };\n\n // search after read\n relatedQuery?: string;\n relatedQueryInfos: { word: string }[];\n\n commentPermission: ECommentPermission;\n illegalInfo?: IIllegalInfo;\n seoBan?: EPostSeoBanStatus;\n}\n\nexport interface IVideoArticleDetail extends IArticleDetail {\n articleClass: EArticleClass.VIDEO;\n largeImage: IImage;\n video: IVideo & { encryptedUrl?: string; ocr?: string[] };\n}\n\nexport interface IGalleryArticleDetail extends IArticleDetail {\n articleClass: EArticleClass.GALLERY;\n imageList: IImage[];\n galleryLabels: GalleryLabelType[];\n ocrText?: string[]; // ocr识别文字\n imageAutoGenDesp?: string[]; // 图片描述自动生成\n}\n\nexport interface IRichArticleDetail extends IArticleDetail {\n articleClass: EArticleClass.ARTICLE;\n largeImage: IImage;\n}\n\nexport type TArticleDetail = IVideoArticleDetail | IGalleryArticleDetail | IRichArticleDetail;\n","import { Region } from '@lemon8/web-app-shared/i18n';\nimport { Comment } from 'schema-dts';\nimport { CommentUtil, TComment } from 'shared/models';\n\nexport const CommentJsonLDUtil = {\n getCommentsJsonLd: (props: { comments: TComment[]; region: Region }): Comment[] => {\n const { comments, region } = props;\n\n return comments.map((item: TComment) => {\n return {\n '@type': 'Comment',\n text: item.text.replace(/\\s/g, ' ') || '',\n author: {\n '@type': 'Person',\n name: item.author.nickName,\n alternateName: item.author.linkName,\n image: item.author.avatar,\n identifier: {\n '@type': 'PropertyValue',\n propertyID: 'Username',\n value: item.author.linkName,\n },\n mainEntityOfPage: {\n '@type': 'ProfilePage',\n '@id': `https://www.lemon8-app.com${CommentUtil.getAuthorPath(item)}?region=${region}`,\n },\n },\n };\n });\n },\n};\n","import { TCommentRichContent } from './rich-content';\nimport { IUserAuthInfo } from 'shared/models/user-auth-info';\nimport { IImage } from '../media';\nimport { CommentJsonLDUtil } from 'shared/models/comments/json-ld-util';\nimport { EUserType, UserTypeUtil } from '../#common';\n\nexport interface IBaseComment {\n commentId: string;\n // timestamp in second\n createTime: number;\n\n author: {\n userId: string;\n avatar: string;\n linkName: string;\n nickName: string;\n authInfo: IUserAuthInfo;\n userType: EUserType;\n };\n\n // content\n text: string;\n richContent?: TCommentRichContent[];\n imageList?: IImage[];\n\n // interaction\n diggCount: number;\n}\n\n/**\n * 1st-level comment\n */\nexport interface IPrimaryComment extends IBaseComment {\n replyCount: number;\n}\n\n/**\n * 2nd-level comment\n */\nexport interface IReply extends IBaseComment {\n replyToCommentId: string;\n}\n\n/**\n * 3rd-level comment\n */\nexport interface IReplyToReply extends IReply {\n replyToReplyId: string;\n}\n\nexport type TComment = IPrimaryComment | IReply | IReplyToReply;\n\nexport const CommentUtil = {\n isReply(comment: TComment): comment is IReply {\n return (comment as IReply).replyToCommentId !== void 0;\n },\n isPrimaryComment(comment: TComment): comment is IPrimaryComment {\n return !CommentUtil.isReply(comment);\n },\n isReplyToReply: (comment: TComment): comment is IReplyToReply => {\n return CommentUtil.isReply(comment) && (comment as IReplyToReply).replyToReplyId !== void 0;\n },\n getAuthorPath: (comment: TComment): string => {\n const prefix = UserTypeUtil.getLinkNamePrefix(comment.author.userType);\n return `/${prefix}${comment.author.linkName}`;\n },\n JsonLd: CommentJsonLDUtil,\n};\n\nexport const CommentRichContentUtil = {};\n","/**\n * 评论富文本类型\n */\nexport enum ECommentRichContentCategory {\n MENTION_USER = 1000,\n}\n\ninterface ICommentRichContent {\n type: ECommentRichContentCategory;\n start: number;\n length: number;\n}\n\nexport interface IMentionUserRichContent extends ICommentRichContent {\n type: ECommentRichContentCategory.MENTION_USER;\n mentionUserId: string;\n}\n\nexport type TCommentRichContent = IMentionUserRichContent;\n","import { Topic, User } from '../legacy';\nimport { IGuessWordCards, IUserDetail, TArticleDetail, TComment } from 'shared/models';\n\ninterface WithLoadmoreOptions {\n items: T[];\n hasMore: boolean;\n minCursor: number;\n maxCursor: number;\n}\n\nexport interface IDiscoverData {\n query: string;\n isBanned: false;\n dataFrom: string;\n article_v2: WithLoadmoreOptions<{\n article: TArticleDetail;\n author: IUserDetail;\n comments: TComment[];\n }>;\n user: WithLoadmoreOptions;\n hashtag: WithLoadmoreOptions;\n guessWordCards: IGuessWordCards;\n}\n\nexport enum EDiscoverUnavailableReason {\n BANNED = 'banned',\n SERVER_ERROR = 'server_error',\n}\n\nexport interface IDiscoverUnavailableData {\n query: string;\n unavailableReason: EDiscoverUnavailableReason;\n}\n\nexport type TDiscoverData = IDiscoverData | IDiscoverUnavailableData;\n","import _get from 'lodash/get';\nimport { IDiscoverData, IDiscoverUnavailableData } from 'shared/models/discover';\n\nexport const DiscoverUtil = {\n Libra: {\n shouldUseSortModel: (parameters: unknown) => Boolean(_get(parameters, 'seo_web.seo_sort_model_webid', 0)),\n shouldFormatAsArticleDetail: (parameters: unknown) => Boolean(_get(parameters, 'seo_web.kep_immersive', 0)),\n },\n isDiscoverDataAvailable: (input: IDiscoverData | IDiscoverUnavailableData): input is IDiscoverData => {\n return !('unavailableReason' in input);\n },\n};\n","import { Article } from '../legacy';\n\nexport enum EExperienceUnavailableReason {\n NO_ANSWER = 'no_answer',\n SERVER_ERROR = 'server_error',\n}\n\nexport interface ExperienceRelatedArticle {\n items: Article[];\n}\n\nexport interface ExperienceAnswerStep {\n title: string;\n content: string;\n sourceList: number[];\n}\n\nexport interface ExperienceGPTAnswer {\n question: string;\n isNewType: boolean;\n answerContent: ExperienceAnswerStep[];\n articleFullContent: string;\n articleShortContent: string;\n articleInfoList: Article[];\n isNumber: boolean;\n submitTimeStamp: number;\n}\n\nexport interface UnavailableExperienceData {\n question: string;\n unavailableReason: EExperienceUnavailableReason;\n isNewType?: boolean;\n}\n","import { IImage, ExperienceGPTAnswer, ArticleAuthor, UserDetailUtil } from 'shared/models';\nimport { ImageObject, Article, Person, InteractionCounter } from 'schema-dts';\nimport type { TFunction } from 'i18next';\nimport { dateToLocalISO } from 'shared/utils/format/time-formatter';\nimport { Region } from '@lemon8/web-app-shared/i18n';\n\nexport const ExperienceJsonLDUtil = {\n getTitle: (props: { experience: ExperienceGPTAnswer; t: TFunction }): string => {\n const { experience, t } = props;\n\n const articleTitle = experience.question;\n const publishYear = new Date(experience.submitTimeStamp * 1000).getFullYear().toString();\n return `${articleTitle} | ${publishYear} ${t('seo_searchCard_link_title')}`;\n },\n getDescription: (props: { experience: ExperienceGPTAnswer }): string => {\n const { experience } = props;\n const { answerContent, articleShortContent, isNewType } = experience;\n\n return isNewType ? articleShortContent : `${answerContent[0].title}: ${answerContent[0].content}`;\n },\n getKeywords: (props: { experience: ExperienceGPTAnswer }): string[] => {\n const { experience } = props;\n\n const result: string[] = [];\n\n const articleTitle = experience.question;\n if (articleTitle) {\n result.push(articleTitle);\n }\n result.push('Lemon8');\n return result;\n },\n getArticleJsonLD: (props: {\n canonicalUrl: string;\n experience: ExperienceGPTAnswer;\n t: TFunction;\n abInfo: Record;\n }): Article => {\n const { experience, canonicalUrl } = props;\n const { articleInfoList, submitTimeStamp } = experience;\n\n const jsonLDTitle = ExperienceJsonLDUtil.getTitle(props);\n const jsonLDDescription = ExperienceJsonLDUtil.getDescription(props);\n const jsonLDKeywords = ExperienceJsonLDUtil.getKeywords(props);\n\n const articleTitle = experience.question;\n\n const imageList: ImageObject[] = [];\n const galleryImageList: IImage[] = [];\n const ocrText: string[] = [];\n const imgCaptions: string[] = [];\n let diggCount = 0;\n\n articleInfoList.forEach((article) => {\n const { articleLikes, largeImage, ocrTextArr = [] } = article;\n galleryImageList.push(largeImage);\n ocrText.push(ocrTextArr[0]);\n imgCaptions.push(article.title);\n diggCount += articleLikes;\n });\n\n const imageListWithExtraInfo = galleryImageList.map((image, index) => {\n return {\n ...image,\n imgOcrText: ocrText[index] || '',\n imgCaption: imgCaptions[index] || '',\n };\n });\n\n imageList.push(\n ...imageListWithExtraInfo.map((image: IImage & { imgCaption: string; imgOcrText: string }): ImageObject => {\n const { imgCaption } = image;\n return {\n '@type': 'ImageObject',\n url: image.url,\n contentUrl: image.url,\n representativeOfPage: 'True',\n keywords: [imgCaption, articleTitle, 'Lemon8'],\n caption: imgCaption,\n embeddedTextCaption: image.imgOcrText || '',\n };\n }),\n );\n\n const articleBaseJsonLD: Article = {\n '@type': 'Article',\n headline: jsonLDTitle,\n description: jsonLDDescription,\n keywords: jsonLDKeywords,\n url: canonicalUrl,\n\n datePublished: dateToLocalISO(submitTimeStamp, /** currently fix timezone to JP. @lidiang */ 9),\n\n image: imageList,\n\n mainEntityOfPage: {\n '@id': canonicalUrl,\n '@type': 'WebPage',\n },\n interactionStatistic: [\n {\n '@type': 'InteractionCounter',\n interactionType: {\n '@type': 'LikeAction',\n },\n userInteractionCount: diggCount,\n },\n ],\n };\n\n return articleBaseJsonLD;\n },\n getPersonJsonLD: (props: { user: ArticleAuthor; userRegion: Region }): Person => {\n const { user, userRegion } = props;\n\n const person: Person = {\n '@type': 'Person',\n url: `https://www.lemon8-app.com${UserDetailUtil.getPath(user)}?region=${userRegion}`,\n name: user.nickName,\n alternateName: user.linkName,\n identifier: {\n '@type': 'PropertyValue',\n propertyID: 'Username',\n value: user.linkName,\n },\n };\n\n const interactionStatistic: InteractionCounter[] = [];\n\n if (user.followerCount) {\n interactionStatistic.push({\n '@type': 'InteractionCounter',\n interactionType: {\n '@type': 'FollowAction',\n },\n userInteractionCount: Number(user.followerCount),\n });\n }\n\n if (user.publishCount) {\n interactionStatistic.push({\n '@type': 'InteractionCounter',\n interactionType: {\n '@type': 'WriteAction',\n },\n userInteractionCount: Number(user.publishCount),\n });\n }\n\n person.interactionStatistic = interactionStatistic;\n\n return person;\n },\n};\n","import { ExperienceGPTAnswer, UnavailableExperienceData } from './types';\nimport { ExperienceJsonLDUtil } from 'shared/models/experience/json-ld-util';\n\nexport const ExperienceUtil = {\n isExperienceDataAvailable: (input: ExperienceGPTAnswer | UnavailableExperienceData): input is ExperienceGPTAnswer => {\n return !('unavailableReason' in input);\n },\n\n JsonLD: ExperienceJsonLDUtil,\n};\n","import { EArticleClass, EUserType, IImage, TArticleDetail, UserTypeUtil } from 'shared/models';\nimport { Region } from '@lemon8/web-app-shared/i18n';\n\nexport interface Article {\n groupId: string;\n\n imprId?: string;\n\n articleClass: EArticleClass;\n\n articleRegion?: Region;\n\n author: ArticleAuthor;\n\n title: string;\n\n shortContent: string;\n\n imageList: IImage[];\n\n largeImage: IImage;\n\n articleLikes: number;\n\n ocrTextArr?: string[];\n}\n\nexport interface ArticleAuthor {\n userId: string;\n\n nickName: string;\n\n linkName: string;\n\n userType: EUserType;\n\n description: string;\n\n avatar: string;\n\n publishCount: number;\n\n authInfo: any;\n\n followerCount?: number;\n}\n\nexport const LegacyArticleUtil = {\n getArticlePath: (article: Article | TArticleDetail): string => {\n return `/${UserTypeUtil.getLinkNamePrefix(article.author.userType)}${article.author.linkName}/${article.groupId}`;\n },\n\n getArticleHref: (article: Article | TArticleDetail): string => {\n const path = LegacyArticleUtil.getArticlePath(article);\n if (article.articleRegion) {\n return `${path}?region=${article.articleRegion}`;\n }\n return path;\n },\n\n getAuthorPath: (article: Article | TArticleDetail): string => {\n return `/${UserTypeUtil.getLinkNamePrefix(article.author.userType)}${article.author.linkName}`;\n },\n};\n","export enum ECategoryNameIDMap {\n follow = '72',\n foryou = '0',\n health = '2',\n food = '12', // 日本 & 泰国 & 印尼\n food_guide = '616', // 日本分拆美食探店频道\n food_recipe = '615', // 日本分拆美食食谱频道\n lifestyle = '19',\n beauty = '569',\n fashion = '570',\n travel = '20',\n profile = '486', // user profile\n poi = '650', // position\n hashtag_channel_recent = '585', // hashtag post by timing\n hashtag_channel_hot = '590', // hashtag post by trending\n relation = '61', // relation article\n pet = '37',\n fitness = '674',\n home = '14',\n productivity = '685',\n reading = '686',\n photography = '669',\n skincare = '668',\n self_growth = '673',\n makeup = '701',\n hair = '702',\n nail = '703',\n outfits = '704',\n skincare_category = '705',\n nails = '706',\n home_category = '707',\n recipes = '708',\n makeup_category = '709',\n hair_style = '710',\n fitness_category = '711',\n accessories = '712',\n mental_health = '714',\n perfume = '715',\n relationship = '677',\n baking = '716',\n shoes = '717',\n wellness = '718',\n music = '216',\n travel_category = '719',\n tattoo = '720',\n drinks = '721',\n home_skills = '723',\n bags = '724',\n movie = '368',\n outdoors = '665',\n tech = '726',\n art_design = '728',\n gardening = '729',\n career = '730',\n games = '731',\n education = '732',\n cars = '687',\n wedding = '734',\n maternity = '736',\n}\n\nexport const CategoryIDNameMap: any = {\n 72: 'follow',\n 0: 'foryou',\n 2: 'health',\n 12: 'food', // 日本 & 泰国 & 印尼\n 616: 'food_guide', // 日本分拆美食探店频道\n 615: 'food_recipe', // 日本分拆美食食谱频道\n 19: 'lifestyle',\n 569: 'beauty',\n 570: 'fashion',\n 20: 'travel',\n 486: 'profile', // user profile\n 650: 'poi', // position\n 585: 'hashtag_channel_recent', // hashtag post by timing\n 590: 'hashtag_channel_hot', // hashtag post by trending\n 61: 'relation', // relation article\n 37: 'pet',\n 674: 'fitness',\n /** us 新增 */\n 14: 'home',\n 685: 'productivity',\n 686: 'reading',\n /** th 新增 */\n 669: 'photography',\n 668: 'skincare',\n 673: 'self_growth',\n 701: 'makeup',\n 702: 'hair',\n 703: 'nail',\n /** US CA AU NZ新增 */\n 704: 'outfits',\n 705: 'skincare_category',\n 706: 'nails',\n 707: 'home_category',\n 708: 'recipes',\n 709: 'makeup_category',\n 710: 'hair_style',\n 711: 'fitness_category',\n 712: 'accessories',\n 714: 'mental_health',\n 715: 'perfume',\n 677: 'relationship',\n 716: 'baking',\n 717: 'shoes',\n 718: 'wellness',\n 216: 'music',\n 719: 'travel_category',\n 720: 'tattoo',\n 721: 'drinks',\n 723: 'home_skills',\n 724: 'bags',\n 368: 'movie',\n 665: 'outdoors',\n 726: 'tech',\n 728: 'art_design',\n 729: 'gardening',\n 730: 'career',\n 731: 'games',\n 732: 'education',\n 687: 'cars',\n 734: 'wedding',\n 736: 'maternity',\n};\n\nexport const CategoryNameIDMap = Object.keys(CategoryIDNameMap).reduce(\n (pre: any, cur: any) => ({\n ...pre,\n [CategoryIDNameMap[cur]]: cur,\n }),\n {},\n);\n","import { Image } from './image';\nimport { EArticleClass, EUserType, UserTypeUtil } from 'shared/models';\n\nexport interface Topic {\n topicId: string;\n topicName: string;\n description: string;\n viewCount: number;\n articles?: TopicArticle[];\n}\n\nexport interface TopicArticle {\n groupId: string;\n\n authorId: string;\n\n authorLinkName: string;\n\n authorType: EUserType;\n\n articleClass: EArticleClass;\n\n title: string;\n\n shortContent: string;\n\n largeImage: Image;\n\n articleLikes: number;\n}\n\nexport const LegacyTopicArticleUtil = {\n getArticlePath: (article: TopicArticle): string => {\n const prefix = UserTypeUtil.getLinkNamePrefix(article.authorType);\n\n return `/${prefix}${article.authorType}/${article.groupId}`;\n },\n\n getAuthorPath: (article: TopicArticle): string => {\n const prefix = UserTypeUtil.getLinkNamePrefix(article.authorType);\n\n return `/${prefix}${article.authorType}`;\n },\n};\n","import { EUserType, UserTypeUtil } from '../#common';\n\nexport interface User {\n userId: string;\n\n nickName: string;\n\n linkName: string;\n\n userType: EUserType;\n\n description: string;\n\n avatar: string;\n\n publishCount: number;\n\n fansCount: number;\n\n authInfo: any;\n}\n\nexport const LegacyUserUtil = {\n getPath: (user: User): string => {\n return `/${UserTypeUtil.getLinkNamePrefix(user.userType)}${user.linkName}`;\n },\n};\n","export interface IMedia {\n url: string;\n\n height: number;\n\n width: number;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface IImage extends IMedia {\n shareCardCoverImage?: string;\n}\n\nexport enum EVideoMuteStatus {\n NORMAL = 0,\n MUTED = 1,\n}\n\nexport interface IVideo extends IMedia {\n muteStatus: EVideoMuteStatus;\n duration: number;\n}\n\nexport const VideoUtils = {\n durationTo8601: (duration: number) => {\n const hour = Math.trunc(duration / 3600);\n const minute = Math.trunc((duration - hour * 3600) / 60);\n const second = Math.trunc(duration - (hour * 3600 + minute * 60));\n let ret = 'PT';\n if (hour) {\n ret += `${hour}H`;\n }\n if (minute) {\n ret += `${minute}M`;\n }\n if ((!hour && !minute) || second) {\n ret += `${second}S`;\n }\n return ret;\n },\n};\n","import { EPageType } from 'shared/models/page-type';\n\nexport interface IPageTraffic {\n canonicalUrl: string;\n pageType: EPageType;\n seoPageId: string;\n currentPid?: string;\n}\n\nexport interface IFeedPageTraffic extends IPageTraffic {\n pageType: EPageType.feed;\n categoryId: string;\n}\n\nexport interface IHashtagPageTraffic extends IPageTraffic {\n pageType: EPageType.hashtag;\n hashtagId: string;\n}\n\nexport interface IArticlePageTraffic extends IPageTraffic {\n pageType: EPageType.article;\n groupId: string;\n mediaId: string;\n contentByTranslate: 0 | 1;\n}\n\nexport interface IVideoPageTraffic extends IPageTraffic {\n pageType: EPageType.video;\n groupId: string;\n mediaId: string;\n contentByTranslate: 0 | 1;\n}\n\nexport interface IPOIPageTraffic extends IPageTraffic {\n pageType: EPageType.poi;\n poiId: string;\n}\n\nexport interface IDiscoverPageTraffic extends IPageTraffic {\n pageType: EPageType.discover;\n keyword: string;\n standardKeyword: string;\n hasBreadCrumb: boolean;\n}\n\nexport interface IExperiencePageTraffic extends IPageTraffic {\n pageType: EPageType.experience | EPageType.experience_article;\n keyword: string;\n hasGPTAnswer: boolean;\n standardKeyword: string;\n question: string;\n}\n\nexport interface IUserPageTraffic extends IPageTraffic {\n pageType: EPageType.user;\n userLinkName: string;\n userId: string;\n}\n\nexport interface IUserFollowPageTraffic extends IPageTraffic {\n pageType: EPageType.user_follow;\n userLinkName: string;\n userId: string;\n}\n\nexport interface IUserTopicPageTraffic extends IPageTraffic {\n pageType: EPageType.user_topic;\n userLinkName: string;\n userId: string;\n}\n\nexport interface ISearchSugPageTraffic extends IPageTraffic {\n pageType: EPageType.search_sug;\n}\n\nexport type PageLevelTraffic =\n | IFeedPageTraffic\n | IHashtagPageTraffic\n | IPOIPageTraffic\n | IArticlePageTraffic\n | IVideoPageTraffic\n | IDiscoverPageTraffic\n | IExperiencePageTraffic\n | IUserPageTraffic\n | IUserFollowPageTraffic\n | IUserTopicPageTraffic\n | ISearchSugPageTraffic;\n\nexport const PageLevelTrafficUtil = {\n getPageIdFromTraffic: (traffic: PageLevelTraffic): string | null => {\n if (traffic.pageType === EPageType.feed) {\n return traffic.categoryId;\n }\n\n if (traffic.pageType === EPageType.hashtag) {\n return traffic.hashtagId;\n }\n\n if (traffic.pageType === EPageType.poi) {\n return traffic.poiId;\n }\n\n if (traffic.pageType === EPageType.article || traffic.pageType === EPageType.video) {\n return traffic.groupId;\n }\n\n if (traffic.pageType === EPageType.discover) {\n return traffic.keyword;\n }\n\n if (traffic.pageType === EPageType.experience || traffic.pageType === EPageType.experience_article) {\n return traffic.keyword;\n }\n\n if (\n traffic.pageType === EPageType.user ||\n traffic.pageType === EPageType.user_follow ||\n traffic.pageType === EPageType.user_topic\n ) {\n return traffic.userId;\n }\n\n return null;\n },\n};\n","export enum EWordType {\n SarWord = 1,\n RSWord = 2,\n GuessWord = 3,\n BreadcrumbsWord = 4,\n}\n\nexport interface SearchWord {\n word: string;\n wordType: EWordType;\n}\n\nexport interface IGuessWordCard {\n words: SearchWord[];\n pos: number;\n}\n\nexport type IGuessWordCards = IGuessWordCard[];\n","export enum SugType {\n normal = 1,\n user = 2,\n hashtag = 3,\n}\n\nexport interface SearchSugItem {\n id: string;\n /** 推荐名称 */\n text: string;\n /** 推荐词类型,目前展示上只区分用户 */\n type: SugType;\n /** 推荐词来源类型,目前展示上只区分是否历史词(服务端返回可能不止这两种类型) */\n rectType: 'normal' | 'history';\n /** 高亮区域,格式[start, end] */\n highlightPos: [number, number];\n /** 用户头像, type为user时候会有该参数 */\n avatar?: string;\n /** 用户user id, type为user时候会有该参数 */\n userId?: string;\n /** 排序(从0开始) */\n rank?: number;\n /** 是否为认证用户 */\n isUserVerify?: boolean;\n /** 是否为绑定 TT 的账户 */\n belongTT?: boolean;\n}\n","export enum ETopicUnavailableReason {\n NOT_FOUND = 'not_found',\n SERVER_ERROR = 'server_error',\n}\n\nexport interface ITopicUnavailableDetail {\n hashtagId: string;\n unavailableReason: ETopicUnavailableReason;\n}\n","import { HashtagInfo } from 'shared/models';\nimport { ITopicUnavailableDetail } from 'shared/models';\n\nexport const TopicUtil = {\n isTopicAvailable: (topic: HashtagInfo | ITopicUnavailableDetail): topic is HashtagInfo => {\n return !('unavailableReason' in topic);\n },\n};\n","import { Article } from '../legacy';\nimport { IImage } from '..';\n\nexport enum PrivacyStatus {\n /** 未取值时 */\n Init = -2,\n /** 正常没有设置privacy的用户 */\n Normal = -1,\n UserPageNoPermission = 0,\n UserPageHasPermission = 1,\n PrivateUser = 2,\n UnderAge = 3,\n}\n\nexport interface UserRelated {\n following_count: number;\n has_more: boolean;\n impr_id: string;\n offset: number;\n session_impr_id: string;\n users: RelatedUser[];\n}\n\nexport interface RelatedUser {\n description: string;\n followers_count: number;\n following_count: number;\n avatar: IImage;\n id: string;\n name: string;\n unique_name: string;\n recommend_reason: string;\n user_auth_info: string;\n user_liked_count: number;\n post_count: number;\n\n article_metas: {\n article_class: string;\n cover_images: IImage[];\n group_id: string;\n img_url: IImage;\n item_id: string;\n short_content: string;\n title: string;\n }[];\n}\n\nexport interface UserPosts {\n items: Article[];\n hasMore: boolean;\n maxBeHotTime?: number;\n offset: number;\n}\n\nexport interface UserInfo {\n // 用户id\n user_id: string;\n user_id_str: string;\n media_id: string;\n media_id_str: string;\n // 用户名,用于展示\n name: string;\n // 用户描述\n description: string;\n // 认证信息\n user_auth_info: string;\n // 1:可展示,0:不可展示\n user_status: number;\n // 头像\n icon_url: string;\n // 1:已关注该用户,0:未关注\n is_following: number;\n // 1:已被该用户关注,0:未被关注\n is_followed: number;\n // 发文数\n posts_count: number;\n // 关注数\n following_count: number;\n // 粉丝数\n followers_count: number;\n // 背景图url\n background_url: string;\n // 分享数\n share_count: number;\n // 用户标签\n user_tags: {\n name: string;\n text: string;\n }[];\n // 拉黑主页用户或被主页用户拉黑,此时不能查看该主页\n is_blocked: boolean;\n // 被主页用户拉黑\n is_blocked_by_profile: boolean;\n // 拉黑主页用户\n is_blocking_profile: boolean;\n privacy_status: PrivacyStatus;\n // 个人网址\n personal_url: string;\n // 用户被点赞总数\n user_liked_count: number;\n // 草稿数量,N项目主态个人页展示\n draft_count: number;\n // 点赞总数\n digg_count: number;\n // 收藏总数\n favorite_count: number;\n tabs: UserTabType[];\n [key: string]: any;\n}\n\nexport interface UserTabType {\n id: string;\n show_name: string;\n is_default: boolean;\n visibility: boolean;\n}\n","import { ESeoBanStatus } from '.';\n\nexport enum EUserUnavailableReason {\n NOT_FOUND = 'not_found',\n SEO_BAN_PRIVATE = 'seo_ban_private',\n SEO_BAN_UNDER_AGE = 'seo_ban_under_age',\n SEO_BAN_UNKNOWN = 'seo_ban_unknown',\n SERVER_ERROR = 'server_error',\n}\n\nexport const SEOBanReasonMap: Record = {\n [ESeoBanStatus.Unknown]: EUserUnavailableReason.SEO_BAN_UNKNOWN,\n [ESeoBanStatus.Private]: EUserUnavailableReason.SEO_BAN_PRIVATE,\n [ESeoBanStatus.UnderAge]: EUserUnavailableReason.SEO_BAN_UNDER_AGE,\n};\n\nexport interface IUserUnavailableDetail {\n userId: string;\n unavailableReason: EUserUnavailableReason;\n seoBan?: ESeoBanStatus;\n}\n","import { Region } from '@lemon8/web-app-shared/i18n';\nimport { InteractionCounter, Person } from 'schema-dts';\nimport { IUserDetail, UserDetailUtil } from 'shared/models';\n\nexport const UserJsonLDUtil = {\n getPersonJsonLD: (props: { user: IUserDetail; userRegion: Region }): Person => {\n const { user, userRegion } = props;\n\n const person: Person = {\n '@type': 'Person',\n url: `https://www.lemon8-app.com${UserDetailUtil.getPath(user)}?region=${userRegion}`,\n name: user.nickName,\n alternateName: user.linkName,\n identifier: {\n '@type': 'PropertyValue',\n propertyID: 'Username',\n value: user.linkName,\n },\n };\n\n const interactionStatistic: InteractionCounter[] = [];\n\n if (user.dugCount || user.favoredCount) {\n interactionStatistic.push({\n '@type': 'InteractionCounter',\n interactionType: {\n '@type': 'LikeAction',\n },\n userInteractionCount: Number(user.dugCount) + Number(user.favoredCount),\n });\n }\n\n if (user.followerCount) {\n interactionStatistic.push({\n '@type': 'InteractionCounter',\n interactionType: {\n '@type': 'FollowAction',\n },\n userInteractionCount: Number(user.followerCount),\n });\n }\n\n if (user.postCount) {\n interactionStatistic.push({\n '@type': 'InteractionCounter',\n interactionType: {\n '@type': 'WriteAction',\n },\n userInteractionCount: Number(user.postCount),\n });\n }\n\n person.interactionStatistic = interactionStatistic;\n\n return person;\n },\n};\n","import { IUserAuthInfo } from 'shared/models/user-auth-info';\nimport { IUserUnavailableDetail, EUserType, UserTypeUtil, ArticleAuthor } from 'shared/models';\nimport { UserJsonLDUtil } from 'shared/models/user/json-ld-util';\n\nexport interface IUserDetail {\n userId: string;\n avatar: string;\n authInfo: IUserAuthInfo;\n nickName: string;\n linkName: string;\n userType: EUserType;\n\n gender: EUserGender;\n ageGroup?: number;\n location?: string;\n\n description: string;\n\n postCount: number;\n diggCount: number;\n dugCount: number;\n favoriteCount: number;\n favoredCount: number;\n followingCount: number;\n followerCount: number;\n\n thirdLinks: {\n platform: string;\n name: string;\n url: string;\n }[];\n\n privacyStatus: EPrivacyStatus;\n seoBan?: ESeoBanStatus;\n\n // banned account\n isBannedAccount: boolean;\n}\n\nexport enum ESeoBanStatus {\n Unknown = 0,\n Private = 1,\n UnderAge = 2,\n}\n\nexport enum EUserGender {\n Unknown = 0,\n MALE = 1,\n FEMALE = 2,\n}\n\nexport enum EPrivacyStatus {\n Normal = -1,\n UserPageNoPermission = 0,\n UserPageHasPermission = 1,\n PrivateUser = 2,\n UnderAge = 3,\n}\n\nexport const UserDetailUtil = {\n isUserAvailable: (user: IUserDetail | IUserUnavailableDetail): user is IUserDetail => {\n return !('unavailableReason' in user);\n },\n getPath: (user: IUserDetail | ArticleAuthor): string => {\n const prefix = UserTypeUtil.getLinkNamePrefix(user.userType);\n\n return `/${prefix}${user.linkName}`;\n },\n JsonLD: UserJsonLDUtil,\n};\n","/**\n * xml 中特殊字符过滤\n * 参考 https://developers.google.com/search/docs/advanced/sitemaps/build-sitemap#sitemap-encoding-guidelines\n */\nexport const escapeSpecialXmlCharacter = (content: string): string =>\n content\n .replace(/&/g, '&')\n .replace(/'/g, ''')\n .replace(/\"/g, '"')\n .replace(/>/g, '>')\n .replace(/\n content\n .replace(/&/g, '&')\n .replace(/'/g, \"'\")\n .replace(/'/g, \"'\")\n .replace(/"/g, '\"')\n .replace(/>/g, '>')\n .replace(/</g, '<');\n\nexport const removeEscapedSpecialXmlCharacter = (content: string): string =>\n content.replace(/&(lt|gt|nbsp|amp|quot);/gi, '');\n","export const dateToLocalISO = function (timeStamp: number, timeZone: number) {\n // off为当地时区相对UTC的偏移量,日本为9,中国为8\n const off = -timeZone * 60;\n const absoff = Math.abs(off);\n return `${\n new Date(timeStamp * 1000 - off * 60 * 1000).toISOString().substr(0, 23) +\n (off > 0 ? '-' : '+') +\n (absoff / 60).toFixed(0).padStart(2, '0')\n }:${(absoff % 60).toString().padStart(2, '0')}`;\n};\n\n/**\n * @Description\n *\n * Get Today and Monday date (yyyy-mm-dd)\n * Used for KEP collection page modified date experiment\n * */\nexport const getTodayAndMondayDate = (): {\n today: string;\n monday: string;\n todayInSlashFormat: string;\n mondayInSlashFormat: string;\n} => {\n const today = new Date();\n const dayOfWeek = today.getDay(); // 0 (Sun) to 6 (Sat)\n const monday = new Date(today); // Start with today\n // Calculate Monday\n const daysSinceMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1;\n monday.setDate(today.getDate() - daysSinceMonday);\n const formatDate = (date: Date, useSlashFormat: boolean) => {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n if (useSlashFormat) {\n return `${year}/${month}/${day}`;\n } else {\n return `${year}-${month}-${day}`;\n }\n };\n return {\n today: formatDate(today, false),\n monday: formatDate(monday, false),\n todayInSlashFormat: formatDate(today, true),\n mondayInSlashFormat: formatDate(monday, true),\n };\n};\n"],"sourceRoot":""}