All checks were successful
Frontend CI / build (push) Successful in 1m8s
### Description - Implement the content page - Parse markdown formant content to html by `markdown-it` - Use `sanitize-html` to prevent from XSS attack - Style the html with `tailwindcss-typography` - Fix the issue when backend parse the password to url - Fix and make the post info list from backend always sorted by id ### Package Changes ### Rust ```toml percent-encoding = "2.3.1" ``` ### Node ```json { "@types/markdown-it": "^14.1.2", "@types/sanitize-html": "^2.16.0", "markdown-it": "^14.1.0", "sanitize-html": "^2.17.0" } ``` ### Screenshots |Desktop|Mobile| |-|-| ||| ### Reference Resolves #45 ### Checklist - [x] A milestone is set - [x] The related issuse has been linked to this branch Reviewed-on: #67 Co-authored-by: SquidSpirit <squid@squidspirit.com> Co-committed-by: SquidSpirit <squid@squidspirit.com>
77 lines
2.0 KiB
TypeScript
77 lines
2.0 KiB
TypeScript
import {
|
|
LabelViewModel,
|
|
type DehydratedLabelProps
|
|
} from '$lib/post/adapter/presenter/labelViewModel';
|
|
import type { PostInfo } from '$lib/post/domain/entity/postInfo';
|
|
|
|
export class PostInfoViewModel {
|
|
readonly id: number;
|
|
readonly title: string;
|
|
readonly description: string;
|
|
readonly previewImageUrl: URL;
|
|
readonly labels: readonly LabelViewModel[];
|
|
readonly publishedTime: Date;
|
|
|
|
private constructor(props: {
|
|
id: number;
|
|
title: string;
|
|
description: string;
|
|
previewImageUrl: URL;
|
|
labels: readonly LabelViewModel[];
|
|
publishedTime: Date;
|
|
}) {
|
|
this.id = props.id;
|
|
this.title = props.title;
|
|
this.description = props.description;
|
|
this.previewImageUrl = props.previewImageUrl;
|
|
this.labels = props.labels;
|
|
this.publishedTime = props.publishedTime;
|
|
}
|
|
|
|
static fromEntity(postInfo: PostInfo): PostInfoViewModel {
|
|
return new PostInfoViewModel({
|
|
id: postInfo.id,
|
|
title: postInfo.title,
|
|
description: postInfo.description,
|
|
previewImageUrl: postInfo.previewImageUrl,
|
|
labels: postInfo.labels.map((label) => LabelViewModel.fromEntity(label)),
|
|
publishedTime: postInfo.publishedTime
|
|
});
|
|
}
|
|
|
|
static rehydrate(props: DehydratedPostInfoProps): PostInfoViewModel {
|
|
return new PostInfoViewModel({
|
|
id: props.id,
|
|
title: props.title,
|
|
description: props.description,
|
|
previewImageUrl: new URL(props.previewImageUrl),
|
|
labels: props.labels.map((label) => LabelViewModel.rehydrate(label)),
|
|
publishedTime: new Date(props.publishedTime)
|
|
});
|
|
}
|
|
|
|
get formattedPublishedTime(): string {
|
|
return this.publishedTime.toISOString().slice(0, 10);
|
|
}
|
|
|
|
dehydrate(): DehydratedPostInfoProps {
|
|
return {
|
|
id: this.id,
|
|
title: this.title,
|
|
description: this.description,
|
|
previewImageUrl: this.previewImageUrl.href,
|
|
labels: this.labels.map((label) => label.dehydrate()),
|
|
publishedTime: this.publishedTime.getTime()
|
|
};
|
|
}
|
|
}
|
|
|
|
export interface DehydratedPostInfoProps {
|
|
id: number;
|
|
title: string;
|
|
description: string;
|
|
previewImageUrl: string;
|
|
labels: DehydratedLabelProps[];
|
|
publishedTime: number;
|
|
}
|