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>
63 lines
1.5 KiB
TypeScript
63 lines
1.5 KiB
TypeScript
import { StatusType, type AsyncState } from '$lib/common/adapter/presenter/asyncState';
|
|
import { PostViewModel } from '$lib/post/adapter/presenter/postViewModel';
|
|
import type { GetPostUseCase } from '$lib/post/application/useCase/getPostUseCase';
|
|
import { get, writable } from 'svelte/store';
|
|
|
|
export type PostState = AsyncState<PostViewModel>;
|
|
export type PostEvent = PostLoadedEvent;
|
|
|
|
export class PostBloc {
|
|
private readonly state = writable<PostState>({
|
|
status: StatusType.Idle
|
|
});
|
|
|
|
constructor(
|
|
private readonly getPostUseCase: GetPostUseCase,
|
|
initialData?: PostViewModel
|
|
) {
|
|
this.state.set({
|
|
status: StatusType.Idle,
|
|
data: initialData
|
|
});
|
|
}
|
|
|
|
get subscribe() {
|
|
return this.state.subscribe;
|
|
}
|
|
|
|
async dispatch(event: PostEvent): Promise<PostState> {
|
|
switch (event.event) {
|
|
case PostEventType.PostLoadedEvent:
|
|
return this.loadPost(event.id);
|
|
}
|
|
}
|
|
|
|
private async loadPost(id: number): Promise<PostState> {
|
|
this.state.set({ status: StatusType.Loading, data: get(this.state).data });
|
|
|
|
const post = await this.getPostUseCase.execute(id);
|
|
if (!post) {
|
|
this.state.set({ status: StatusType.Error, error: new Error('Post not found') });
|
|
return get(this.state);
|
|
}
|
|
|
|
const postViewModel = PostViewModel.fromEntity(post);
|
|
const result: PostState = {
|
|
status: StatusType.Success,
|
|
data: postViewModel
|
|
};
|
|
|
|
this.state.set(result);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
export enum PostEventType {
|
|
PostLoadedEvent
|
|
}
|
|
|
|
export interface PostLoadedEvent {
|
|
event: PostEventType.PostLoadedEvent;
|
|
id: number;
|
|
}
|