mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2026-04-06 01:25:31 +00:00
refactor(backend): remove content excerpt (#9441)
This commit is contained in:
parent
33f522ed16
commit
b088ec9e62
@ -199,9 +199,6 @@ Factory.define('post')
|
|||||||
// Convert false to null
|
// Convert false to null
|
||||||
return pinned || null
|
return pinned || null
|
||||||
})
|
})
|
||||||
.attr('contentExcerpt', ['contentExcerpt', 'content'], (contentExcerpt, content) => {
|
|
||||||
return contentExcerpt || content
|
|
||||||
})
|
|
||||||
.attr('slug', ['slug', 'title'], (slug, title) => {
|
.attr('slug', ['slug', 'title'], (slug, title) => {
|
||||||
return slug || slugify(title, { lower: true })
|
return slug || slugify(title, { lower: true })
|
||||||
})
|
})
|
||||||
@ -294,9 +291,6 @@ Factory.define('comment')
|
|||||||
id: uuid,
|
id: uuid,
|
||||||
content: faker.lorem.sentence,
|
content: faker.lorem.sentence,
|
||||||
})
|
})
|
||||||
.attr('contentExcerpt', ['contentExcerpt', 'content'], (contentExcerpt, content) => {
|
|
||||||
return contentExcerpt || content
|
|
||||||
})
|
|
||||||
.after(async (buildObject, options) => {
|
.after(async (buildObject, options) => {
|
||||||
const [comment, author, post] = await Promise.all([
|
const [comment, author, post] = await Promise.all([
|
||||||
neode.create('Comment', buildObject),
|
neode.create('Comment', buildObject),
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||||
|
|
||||||
|
import { getDriver } from '@db/neo4j'
|
||||||
|
|
||||||
|
export const description = 'Remove contentExcerpt property from Post and Comment nodes'
|
||||||
|
|
||||||
|
export async function up(_next) {
|
||||||
|
const driver = getDriver()
|
||||||
|
const session = driver.session()
|
||||||
|
const transaction = session.beginTransaction()
|
||||||
|
|
||||||
|
try {
|
||||||
|
await transaction.run(`
|
||||||
|
MATCH (n)
|
||||||
|
WHERE n:Post OR n:Comment
|
||||||
|
REMOVE n.contentExcerpt
|
||||||
|
`)
|
||||||
|
await transaction.commit()
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error)
|
||||||
|
await transaction.rollback()
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('rolled back')
|
||||||
|
throw new Error(error)
|
||||||
|
} finally {
|
||||||
|
await session.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function down(_next) {
|
||||||
|
throw new Error(
|
||||||
|
'Irreversible migration: contentExcerpt was removed and cannot be restored without regenerating from content',
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -10,7 +10,6 @@ export default {
|
|||||||
default: () => new Date().toISOString(),
|
default: () => new Date().toISOString(),
|
||||||
},
|
},
|
||||||
content: { type: 'string', disallow: [null], min: 3 },
|
content: { type: 'string', disallow: [null], min: 3 },
|
||||||
contentExcerpt: { type: 'string', allow: [null] },
|
|
||||||
deleted: { type: 'boolean', default: false },
|
deleted: { type: 'boolean', default: false },
|
||||||
disabled: { type: 'boolean', default: false },
|
disabled: { type: 'boolean', default: false },
|
||||||
post: {
|
post: {
|
||||||
|
|||||||
@ -19,7 +19,6 @@ export default {
|
|||||||
title: { type: 'string', disallow: [null], min: 3 },
|
title: { type: 'string', disallow: [null], min: 3 },
|
||||||
slug: { type: 'string', allow: [null], unique: 'true' },
|
slug: { type: 'string', allow: [null], unique: 'true' },
|
||||||
content: { type: 'string', disallow: [null], required: true, min: 3 },
|
content: { type: 'string', disallow: [null], required: true, min: 3 },
|
||||||
contentExcerpt: { type: 'string', allow: [null] },
|
|
||||||
deleted: { type: 'boolean', default: false },
|
deleted: { type: 'boolean', default: false },
|
||||||
disabled: { type: 'boolean', default: false },
|
disabled: { type: 'boolean', default: false },
|
||||||
clickedCount: { type: 'int', default: 0 },
|
clickedCount: { type: 'int', default: 0 },
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import type { Integer, Node } from 'neo4j-driver'
|
|||||||
|
|
||||||
export interface CommentDbProperties {
|
export interface CommentDbProperties {
|
||||||
content: string
|
content: string
|
||||||
contentExcerpt: string
|
|
||||||
createdAt: string
|
createdAt: string
|
||||||
deleted: boolean
|
deleted: boolean
|
||||||
disabled: boolean
|
disabled: boolean
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import type { Integer, Node } from 'neo4j-driver'
|
|||||||
export interface PostDbProperties {
|
export interface PostDbProperties {
|
||||||
clickedCount: number
|
clickedCount: number
|
||||||
content: string
|
content: string
|
||||||
contentExcerpt: string
|
|
||||||
createdAt: string
|
createdAt: string
|
||||||
deleted: boolean
|
deleted: boolean
|
||||||
disabled: boolean
|
disabled: boolean
|
||||||
|
|||||||
@ -2,7 +2,6 @@ mutation DeleteComment($id: ID!) {
|
|||||||
DeleteComment(id: $id) {
|
DeleteComment(id: $id) {
|
||||||
id
|
id
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
deleted
|
deleted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,6 @@ mutation DeletePost($id: ID!) {
|
|||||||
id
|
id
|
||||||
deleted
|
deleted
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
image {
|
image {
|
||||||
url
|
url
|
||||||
}
|
}
|
||||||
@ -11,7 +10,6 @@ mutation DeletePost($id: ID!) {
|
|||||||
id
|
id
|
||||||
deleted
|
deleted
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,6 @@ query Post($id: ID, $filter: _PostFilter, $first: Int, $offset: Int, $orderBy: [
|
|||||||
id
|
id
|
||||||
title
|
title
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
eventStart
|
eventStart
|
||||||
pinned
|
pinned
|
||||||
createdAt
|
createdAt
|
||||||
|
|||||||
@ -7,19 +7,16 @@ mutation DeleteUser($id: ID!, $resource: [Deletable]) {
|
|||||||
contributions {
|
contributions {
|
||||||
id
|
id
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
deleted
|
deleted
|
||||||
comments {
|
comments {
|
||||||
id
|
id
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
deleted
|
deleted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
comments {
|
comments {
|
||||||
id
|
id
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
deleted
|
deleted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,6 @@ query User($id: ID, $name: String, $email: String) {
|
|||||||
comments {
|
comments {
|
||||||
id
|
id
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
}
|
}
|
||||||
contributions {
|
contributions {
|
||||||
id
|
id
|
||||||
@ -39,7 +38,6 @@ query User($id: ID, $name: String, $email: String) {
|
|||||||
url
|
url
|
||||||
}
|
}
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isMuted
|
isMuted
|
||||||
|
|||||||
@ -30,7 +30,6 @@ query UserEmail($id: ID, $name: String, $email: String) {
|
|||||||
comments {
|
comments {
|
||||||
id
|
id
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
}
|
}
|
||||||
contributions {
|
contributions {
|
||||||
id
|
id
|
||||||
@ -40,7 +39,6 @@ query UserEmail($id: ID, $name: String, $email: String) {
|
|||||||
url
|
url
|
||||||
}
|
}
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isMuted
|
isMuted
|
||||||
|
|||||||
@ -29,7 +29,6 @@ query UserEmailNotificationSettings($id: ID, $name: String, $email: String) {
|
|||||||
comments {
|
comments {
|
||||||
id
|
id
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
}
|
}
|
||||||
contributions {
|
contributions {
|
||||||
id
|
id
|
||||||
@ -39,7 +38,6 @@ query UserEmailNotificationSettings($id: ID, $name: String, $email: String) {
|
|||||||
url
|
url
|
||||||
}
|
}
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isMuted
|
isMuted
|
||||||
|
|||||||
@ -240,7 +240,6 @@ describe('DeleteComment', () => {
|
|||||||
id: 'c456',
|
id: 'c456',
|
||||||
deleted: true,
|
deleted: true,
|
||||||
content: 'UNAVAILABLE',
|
content: 'UNAVAILABLE',
|
||||||
contentExcerpt: 'UNAVAILABLE',
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
expect(data).toMatchObject(expected)
|
expect(data).toMatchObject(expected)
|
||||||
|
|||||||
@ -83,7 +83,6 @@ export default {
|
|||||||
MATCH (comment:Comment {id: $commentId})
|
MATCH (comment:Comment {id: $commentId})
|
||||||
SET comment.deleted = TRUE
|
SET comment.deleted = TRUE
|
||||||
SET comment.content = 'UNAVAILABLE'
|
SET comment.content = 'UNAVAILABLE'
|
||||||
SET comment.contentExcerpt = 'UNAVAILABLE'
|
|
||||||
RETURN comment
|
RETURN comment
|
||||||
`,
|
`,
|
||||||
{ commentId: args.id },
|
{ commentId: args.id },
|
||||||
|
|||||||
@ -2000,7 +2000,6 @@ describe('DeletePost', () => {
|
|||||||
id: 'p4711',
|
id: 'p4711',
|
||||||
deleted: true,
|
deleted: true,
|
||||||
content: 'UNAVAILABLE',
|
content: 'UNAVAILABLE',
|
||||||
contentExcerpt: 'UNAVAILABLE',
|
|
||||||
image: null,
|
image: null,
|
||||||
comments: [],
|
comments: [],
|
||||||
},
|
},
|
||||||
@ -2015,7 +2014,6 @@ describe('DeletePost', () => {
|
|||||||
'comment',
|
'comment',
|
||||||
{
|
{
|
||||||
content: 'to be deleted comment content',
|
content: 'to be deleted comment content',
|
||||||
contentExcerpt: 'to be deleted comment content',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
postId: 'p4711',
|
postId: 'p4711',
|
||||||
@ -2030,14 +2028,12 @@ describe('DeletePost', () => {
|
|||||||
id: 'p4711',
|
id: 'p4711',
|
||||||
deleted: true,
|
deleted: true,
|
||||||
content: 'UNAVAILABLE',
|
content: 'UNAVAILABLE',
|
||||||
contentExcerpt: 'UNAVAILABLE',
|
|
||||||
image: null,
|
image: null,
|
||||||
comments: [
|
comments: [
|
||||||
{
|
{
|
||||||
deleted: true,
|
deleted: true,
|
||||||
// Should we black out the comment content in the database, too?
|
// Should we black out the comment content in the database, too?
|
||||||
content: 'UNAVAILABLE',
|
content: 'UNAVAILABLE',
|
||||||
contentExcerpt: 'UNAVAILABLE',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@ -296,7 +296,6 @@ export default {
|
|||||||
OPTIONAL MATCH (post)<-[:COMMENTS]-(comment:Comment)
|
OPTIONAL MATCH (post)<-[:COMMENTS]-(comment:Comment)
|
||||||
SET post.deleted = TRUE
|
SET post.deleted = TRUE
|
||||||
SET post.content = 'UNAVAILABLE'
|
SET post.content = 'UNAVAILABLE'
|
||||||
SET post.contentExcerpt = 'UNAVAILABLE'
|
|
||||||
SET post.title = 'UNAVAILABLE'
|
SET post.title = 'UNAVAILABLE'
|
||||||
SET comment.deleted = TRUE
|
SET comment.deleted = TRUE
|
||||||
RETURN post {.*}
|
RETURN post {.*}
|
||||||
|
|||||||
@ -354,13 +354,11 @@ describe('Delete a User as admin', () => {
|
|||||||
{
|
{
|
||||||
id: 'p139',
|
id: 'p139',
|
||||||
content: 'Post by user u343',
|
content: 'Post by user u343',
|
||||||
contentExcerpt: 'Post by user u343',
|
|
||||||
deleted: false,
|
deleted: false,
|
||||||
comments: [
|
comments: [
|
||||||
{
|
{
|
||||||
id: 'c156',
|
id: 'c156',
|
||||||
content: "A comment by someone else on user u343's post",
|
content: "A comment by someone else on user u343's post",
|
||||||
contentExcerpt: "A comment by someone else on user u343's post",
|
|
||||||
deleted: false,
|
deleted: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -370,7 +368,6 @@ describe('Delete a User as admin', () => {
|
|||||||
{
|
{
|
||||||
id: 'c155',
|
id: 'c155',
|
||||||
content: 'Comment by user u343',
|
content: 'Comment by user u343',
|
||||||
contentExcerpt: 'Comment by user u343',
|
|
||||||
deleted: false,
|
deleted: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -400,13 +397,11 @@ describe('Delete a User as admin', () => {
|
|||||||
{
|
{
|
||||||
id: 'p139',
|
id: 'p139',
|
||||||
content: 'UNAVAILABLE',
|
content: 'UNAVAILABLE',
|
||||||
contentExcerpt: 'UNAVAILABLE',
|
|
||||||
deleted: true,
|
deleted: true,
|
||||||
comments: [
|
comments: [
|
||||||
{
|
{
|
||||||
id: 'c156',
|
id: 'c156',
|
||||||
content: 'UNAVAILABLE',
|
content: 'UNAVAILABLE',
|
||||||
contentExcerpt: 'UNAVAILABLE',
|
|
||||||
deleted: true,
|
deleted: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -416,7 +411,6 @@ describe('Delete a User as admin', () => {
|
|||||||
{
|
{
|
||||||
id: 'c155',
|
id: 'c155',
|
||||||
content: 'UNAVAILABLE',
|
content: 'UNAVAILABLE',
|
||||||
contentExcerpt: 'UNAVAILABLE',
|
|
||||||
deleted: true,
|
deleted: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -223,7 +223,6 @@ export default {
|
|||||||
OPTIONAL MATCH (resource)<-[:COMMENTS]-(comment:Comment)
|
OPTIONAL MATCH (resource)<-[:COMMENTS]-(comment:Comment)
|
||||||
SET resource.deleted = true
|
SET resource.deleted = true
|
||||||
SET resource.content = 'UNAVAILABLE'
|
SET resource.content = 'UNAVAILABLE'
|
||||||
SET resource.contentExcerpt = 'UNAVAILABLE'
|
|
||||||
SET resource.language = 'UNAVAILABLE'
|
SET resource.language = 'UNAVAILABLE'
|
||||||
SET resource.createdAt = 'UNAVAILABLE'
|
SET resource.createdAt = 'UNAVAILABLE'
|
||||||
SET resource.updatedAt = 'UNAVAILABLE'
|
SET resource.updatedAt = 'UNAVAILABLE'
|
||||||
|
|||||||
@ -41,7 +41,6 @@ type Comment {
|
|||||||
activityId: String
|
activityId: String
|
||||||
author: User @relation(name: "WROTE", direction: "IN")
|
author: User @relation(name: "WROTE", direction: "IN")
|
||||||
content: String!
|
content: String!
|
||||||
contentExcerpt: String
|
|
||||||
post: Post @relation(name: "COMMENTS", direction: "OUT")
|
post: Post @relation(name: "COMMENTS", direction: "OUT")
|
||||||
createdAt: String
|
createdAt: String
|
||||||
updatedAt: String
|
updatedAt: String
|
||||||
@ -81,7 +80,7 @@ type Query {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
CreateComment(id: ID, postId: ID!, content: String!, contentExcerpt: String): Comment
|
CreateComment(id: ID, postId: ID!, content: String!): Comment
|
||||||
UpdateComment(id: ID!, content: String!, contentExcerpt: String): Comment
|
UpdateComment(id: ID!, content: String!): Comment
|
||||||
DeleteComment(id: ID!): Comment
|
DeleteComment(id: ID!): Comment
|
||||||
}
|
}
|
||||||
|
|||||||
@ -129,7 +129,6 @@ type Post {
|
|||||||
title: String!
|
title: String!
|
||||||
slug: String!
|
slug: String!
|
||||||
content: String!
|
content: String!
|
||||||
contentExcerpt: String
|
|
||||||
image: Image @relation(name: "HERO_IMAGE", direction: "OUT")
|
image: Image @relation(name: "HERO_IMAGE", direction: "OUT")
|
||||||
visibility: Visibility
|
visibility: Visibility
|
||||||
deleted: Boolean
|
deleted: Boolean
|
||||||
@ -230,7 +229,6 @@ type Mutation {
|
|||||||
visibility: Visibility
|
visibility: Visibility
|
||||||
language: String
|
language: String
|
||||||
categoryIds: [ID]
|
categoryIds: [ID]
|
||||||
contentExcerpt: String
|
|
||||||
groupId: ID
|
groupId: ID
|
||||||
postType: PostType = Article
|
postType: PostType = Article
|
||||||
eventInput: _EventInput
|
eventInput: _EventInput
|
||||||
@ -240,7 +238,6 @@ type Mutation {
|
|||||||
title: String!
|
title: String!
|
||||||
slug: String
|
slug: String
|
||||||
content: String!
|
content: String!
|
||||||
contentExcerpt: String
|
|
||||||
image: ImageInput
|
image: ImageInput
|
||||||
visibility: Visibility
|
visibility: Visibility
|
||||||
language: String
|
language: String
|
||||||
|
|||||||
@ -20,33 +20,9 @@ const updateGroup: IMiddlewareResolver = async (resolve, root, args, context, in
|
|||||||
return resolve(root, args, context, info)
|
return resolve(root, args, context, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
const createPost: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
|
||||||
args.contentExcerpt = trunc(args.content, 120).html
|
|
||||||
return resolve(root, args, context, info)
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatePost: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
|
||||||
args.contentExcerpt = trunc(args.content, 120).html
|
|
||||||
return resolve(root, args, context, info)
|
|
||||||
}
|
|
||||||
|
|
||||||
const createComment: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
|
||||||
args.contentExcerpt = trunc(args.content, 180).html
|
|
||||||
return resolve(root, args, context, info)
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateComment: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
|
||||||
args.contentExcerpt = trunc(args.content, 180).html
|
|
||||||
return resolve(root, args, context, info)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Mutation: {
|
Mutation: {
|
||||||
CreateGroup: createGroup,
|
CreateGroup: createGroup,
|
||||||
UpdateGroup: updateGroup,
|
UpdateGroup: updateGroup,
|
||||||
CreatePost: createPost,
|
|
||||||
UpdatePost: updatePost,
|
|
||||||
CreateComment: createComment,
|
|
||||||
UpdateComment: updateComment,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -116,7 +116,6 @@ beforeAll(async () => {
|
|||||||
id: 'p2',
|
id: 'p2',
|
||||||
title: 'Disabled post',
|
title: 'Disabled post',
|
||||||
content: 'This is an offensive post content',
|
content: 'This is an offensive post content',
|
||||||
contentExcerpt: 'This is an offensive post content',
|
|
||||||
deleted: false,
|
deleted: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -132,7 +131,6 @@ beforeAll(async () => {
|
|||||||
{
|
{
|
||||||
id: 'c1',
|
id: 'c1',
|
||||||
content: 'Disabled comment',
|
content: 'Disabled comment',
|
||||||
contentExcerpt: 'Disabled comment',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
author: troll,
|
author: troll,
|
||||||
@ -252,9 +250,6 @@ describe('softDeleteMiddleware', () => {
|
|||||||
it('displays content', () => {
|
it('displays content', () => {
|
||||||
expect(subject.content).toEqual('This is an offensive post content')
|
expect(subject.content).toEqual('This is an offensive post content')
|
||||||
})
|
})
|
||||||
it('displays contentExcerpt', () => {
|
|
||||||
expect(subject.contentExcerpt).toEqual('This is an offensive post content')
|
|
||||||
})
|
|
||||||
it('displays image', () => {
|
it('displays image', () => {
|
||||||
expect(subject.image).toEqual({
|
expect(subject.image).toEqual({
|
||||||
url: expect.stringMatching('http://localhost/some/offensive/image.jpg'),
|
url: expect.stringMatching('http://localhost/some/offensive/image.jpg'),
|
||||||
@ -268,9 +263,6 @@ describe('softDeleteMiddleware', () => {
|
|||||||
it('displays content', () => {
|
it('displays content', () => {
|
||||||
expect(subject.content).toEqual('Disabled comment')
|
expect(subject.content).toEqual('Disabled comment')
|
||||||
})
|
})
|
||||||
it('displays contentExcerpt', () => {
|
|
||||||
expect(subject.contentExcerpt).toEqual('Disabled comment')
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -308,9 +300,6 @@ describe('softDeleteMiddleware', () => {
|
|||||||
it('obfuscates content', () => {
|
it('obfuscates content', () => {
|
||||||
expect(subject.content).toEqual('UNAVAILABLE')
|
expect(subject.content).toEqual('UNAVAILABLE')
|
||||||
})
|
})
|
||||||
it('obfuscates contentExcerpt', () => {
|
|
||||||
expect(subject.contentExcerpt).toEqual('UNAVAILABLE')
|
|
||||||
})
|
|
||||||
it('obfuscates image', () => {
|
it('obfuscates image', () => {
|
||||||
expect(subject.image).toEqual(null)
|
expect(subject.image).toEqual(null)
|
||||||
})
|
})
|
||||||
@ -322,9 +311,6 @@ describe('softDeleteMiddleware', () => {
|
|||||||
it('obfuscates content', () => {
|
it('obfuscates content', () => {
|
||||||
expect(subject.content).toEqual('UNAVAILABLE')
|
expect(subject.content).toEqual('UNAVAILABLE')
|
||||||
})
|
})
|
||||||
it('obfuscates contentExcerpt', () => {
|
|
||||||
expect(subject.contentExcerpt).toEqual('UNAVAILABLE')
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -20,7 +20,6 @@ const setDefaultFilters: IMiddlewareResolver = async (resolve, root, args, conte
|
|||||||
const obfuscate: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
const obfuscate: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
||||||
if (root.deleted || (!isModerator(context) && root.disabled)) {
|
if (root.deleted || (!isModerator(context) && root.disabled)) {
|
||||||
root.content = 'UNAVAILABLE'
|
root.content = 'UNAVAILABLE'
|
||||||
root.contentExcerpt = 'UNAVAILABLE'
|
|
||||||
root.title = 'UNAVAILABLE'
|
root.title = 'UNAVAILABLE'
|
||||||
root.slug = 'UNAVAILABLE'
|
root.slug = 'UNAVAILABLE'
|
||||||
root.avatar = null
|
root.avatar = null
|
||||||
|
|||||||
@ -41,7 +41,7 @@ const walkRecursive = (data, fields, fieldName, callback, _key?) => {
|
|||||||
// exclamation mark separates field names, that should not be sanitized
|
// exclamation mark separates field names, that should not be sanitized
|
||||||
const fields = [
|
const fields = [
|
||||||
{ field: 'content', excludes: ['CreateMessage', 'Message'] },
|
{ field: 'content', excludes: ['CreateMessage', 'Message'] },
|
||||||
{ field: 'contentExcerpt' },
|
|
||||||
{ field: 'reasonDescription' },
|
{ field: 'reasonDescription' },
|
||||||
{ field: 'description', excludes: ['embed'] },
|
{ field: 'description', excludes: ['embed'] },
|
||||||
{ field: 'descriptionExcerpt' },
|
{ field: 'descriptionExcerpt' },
|
||||||
|
|||||||
@ -34,7 +34,7 @@ defineStep('I see all the reported posts including the one from above', () => {
|
|||||||
}
|
}
|
||||||
... on Comment {
|
... on Comment {
|
||||||
id
|
id
|
||||||
contentExcerpt
|
content
|
||||||
disabled
|
disabled
|
||||||
deleted
|
deleted
|
||||||
author {
|
author {
|
||||||
|
|||||||
@ -159,7 +159,7 @@ export default {
|
|||||||
titleIdent: 'delete.comment.title',
|
titleIdent: 'delete.comment.title',
|
||||||
messageIdent: 'delete.comment.message',
|
messageIdent: 'delete.comment.message',
|
||||||
messageParams: {
|
messageParams: {
|
||||||
name: this.$filters.truncate(this.comment.contentExcerpt, 30),
|
name: this.$filters.truncate(this.$filters.removeHtml(this.comment.content), 30),
|
||||||
},
|
},
|
||||||
buttons: {
|
buttons: {
|
||||||
confirm: {
|
confirm: {
|
||||||
|
|||||||
@ -100,7 +100,7 @@ describe('NotificationsTable.vue', () => {
|
|||||||
it("renders the Post's content", () => {
|
it("renders the Post's content", () => {
|
||||||
const boldTags = firstRowNotification.findAll('p')
|
const boldTags = firstRowNotification.findAll('p')
|
||||||
const content = boldTags.filter(
|
const content = boldTags.filter(
|
||||||
(element) => element.text() === postNotification.from.contentExcerpt,
|
(element) => element.text() === postNotification.from.content,
|
||||||
)
|
)
|
||||||
expect(content.exists()).toBe(true)
|
expect(content.exists()).toBe(true)
|
||||||
})
|
})
|
||||||
@ -133,12 +133,34 @@ describe('NotificationsTable.vue', () => {
|
|||||||
it("renders the Post's content", () => {
|
it("renders the Post's content", () => {
|
||||||
const boldTags = secondRowNotification.findAll('p')
|
const boldTags = secondRowNotification.findAll('p')
|
||||||
const content = boldTags.filter(
|
const content = boldTags.filter(
|
||||||
(element) => element.text() === commentNotification.from.contentExcerpt,
|
(element) => element.text() === commentNotification.from.content,
|
||||||
)
|
)
|
||||||
expect(content.exists()).toBe(true)
|
expect(content.exists()).toBe(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('fallback to descriptionExcerpt when content is empty', () => {
|
||||||
|
it('renders descriptionExcerpt if content is missing', () => {
|
||||||
|
const fallbackNotification = {
|
||||||
|
read: false,
|
||||||
|
reason: 'mentioned_in_post',
|
||||||
|
from: {
|
||||||
|
__typename: 'Post',
|
||||||
|
id: 'post-fallback',
|
||||||
|
title: 'fallback post',
|
||||||
|
slug: 'fallback-post',
|
||||||
|
content: '',
|
||||||
|
descriptionExcerpt: 'fallback description text',
|
||||||
|
author: { id: 'u1', slug: 'user', name: 'User' },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
propsData.notifications = [fallbackNotification]
|
||||||
|
wrapper = Wrapper()
|
||||||
|
const description = wrapper.find('.notification-description')
|
||||||
|
expect(description.text()).toBe('fallback description text')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('unread status', () => {
|
describe('unread status', () => {
|
||||||
it('does not have class `notification-status`', () => {
|
it('does not have class `notification-status`', () => {
|
||||||
expect(wrapper.find('.notification-status').exists()).toBe(false)
|
expect(wrapper.find('.notification-status').exists()).toBe(false)
|
||||||
|
|||||||
@ -32,8 +32,6 @@ export const notifications = [
|
|||||||
deleted: false,
|
deleted: false,
|
||||||
content:
|
content:
|
||||||
'<p><a class="mention" href="/profile/u1" data-mention-id="u1" target="_blank">@peter-lustig</a> </p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Turpis egestas pretium aenean pharetra magna ac placerat. Tempor id eu nisl nunc mi ipsum faucibus vitae. Nibh praesent tristique magna sit amet purus gravida quis blandit. Magna eget est lorem ipsum dolor. In fermentum posuere urna nec. Eleifend donec pretium vulputate sapien nec sagittis aliquam. Augue interdum velit euismod in pellentesque. Id diam maecenas ultricies mi eget mauris pharetra. Donec pretium vulputate sapien nec. Dolor morbi non arcu risus quis varius quam quisque. Blandit turpis cursus in hac habitasse. Est ultricies integer quis auctor elit sed vulputate mi sit. Nunc consequat interdum varius sit amet mattis vulputate enim. Semper feugiat nibh sed pulvinar. Eget felis eget nunc lobortis mattis aliquam. Ultrices vitae auctor eu augue. Tellus molestie nunc non blandit massa enim nec dui. Pharetra massa massa ultricies mi quis hendrerit dolor. Nisl suscipit adipiscing bibendum est ultricies integer.</p>',
|
'<p><a class="mention" href="/profile/u1" data-mention-id="u1" target="_blank">@peter-lustig</a> </p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Turpis egestas pretium aenean pharetra magna ac placerat. Tempor id eu nisl nunc mi ipsum faucibus vitae. Nibh praesent tristique magna sit amet purus gravida quis blandit. Magna eget est lorem ipsum dolor. In fermentum posuere urna nec. Eleifend donec pretium vulputate sapien nec sagittis aliquam. Augue interdum velit euismod in pellentesque. Id diam maecenas ultricies mi eget mauris pharetra. Donec pretium vulputate sapien nec. Dolor morbi non arcu risus quis varius quam quisque. Blandit turpis cursus in hac habitasse. Est ultricies integer quis auctor elit sed vulputate mi sit. Nunc consequat interdum varius sit amet mattis vulputate enim. Semper feugiat nibh sed pulvinar. Eget felis eget nunc lobortis mattis aliquam. Ultrices vitae auctor eu augue. Tellus molestie nunc non blandit massa enim nec dui. Pharetra massa massa ultricies mi quis hendrerit dolor. Nisl suscipit adipiscing bibendum est ultricies integer.</p>',
|
||||||
contentExcerpt:
|
|
||||||
'<p><a href="/profile/u1" target="_blank">@peter-lustig</a> </p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Turpis egestas pretium aenean pharetra …</p>',
|
|
||||||
...post,
|
...post,
|
||||||
author: user,
|
author: user,
|
||||||
},
|
},
|
||||||
@ -53,8 +51,6 @@ export const notifications = [
|
|||||||
deleted: false,
|
deleted: false,
|
||||||
content:
|
content:
|
||||||
'<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Turpis egestas pretium aenean pharetra magna ac placerat. Tempor id eu nisl nunc mi ipsum faucibus vitae. Nibh praesent tristique magna sit amet purus gravida quis blandit. Magna eget est lorem ipsum dolor. In fermentum posuere urna nec. Eleifend donec pretium vulputate sapien nec sagittis aliquam. Augue interdum velit euismod in pellentesque. Id diam maecenas ultricies mi eget mauris pharetra. Donec pretium vulputate sapien nec. Dolor morbi non arcu risus quis varius quam quisque. Blandit turpis cursus in hac habitasse. Est ultricies integer quis auctor elit sed vulputate mi sit. Nunc consequat interdum varius sit amet mattis vulputate enim. Semper feugiat nibh sed pulvinar. Eget felis eget nunc lobortis mattis aliquam. Ultrices vitae auctor eu augue. Tellus molestie nunc non blandit massa enim nec dui. Pharetra massa massa ultricies mi quis hendrerit dolor. Nisl suscipit adipiscing bibendum est ultricies integer.</p><p><a class="mention" href="/profile/u1" data-mention-id="u1" target="_blank">@peter-lustig</a> </p><p></p>',
|
'<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Turpis egestas pretium aenean pharetra magna ac placerat. Tempor id eu nisl nunc mi ipsum faucibus vitae. Nibh praesent tristique magna sit amet purus gravida quis blandit. Magna eget est lorem ipsum dolor. In fermentum posuere urna nec. Eleifend donec pretium vulputate sapien nec sagittis aliquam. Augue interdum velit euismod in pellentesque. Id diam maecenas ultricies mi eget mauris pharetra. Donec pretium vulputate sapien nec. Dolor morbi non arcu risus quis varius quam quisque. Blandit turpis cursus in hac habitasse. Est ultricies integer quis auctor elit sed vulputate mi sit. Nunc consequat interdum varius sit amet mattis vulputate enim. Semper feugiat nibh sed pulvinar. Eget felis eget nunc lobortis mattis aliquam. Ultrices vitae auctor eu augue. Tellus molestie nunc non blandit massa enim nec dui. Pharetra massa massa ultricies mi quis hendrerit dolor. Nisl suscipit adipiscing bibendum est ultricies integer.</p><p><a class="mention" href="/profile/u1" data-mention-id="u1" target="_blank">@peter-lustig</a> </p><p></p>',
|
||||||
contentExcerpt:
|
|
||||||
'<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Turpis egestas pretium aenean pharetra magna ac …</p>',
|
|
||||||
...post,
|
...post,
|
||||||
author: user,
|
author: user,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -72,8 +72,8 @@
|
|||||||
:class="{ 'notification-status': notification.read }"
|
:class="{ 'notification-status': notification.read }"
|
||||||
>
|
>
|
||||||
{{
|
{{
|
||||||
notification.from.contentExcerpt ||
|
$filters.removeHtml(notification.from.content) ||
|
||||||
notification.from.descriptionExcerpt | removeHtml
|
$filters.removeHtml(notification.from.descriptionExcerpt)
|
||||||
}}
|
}}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -66,9 +66,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</client-only>
|
</client-only>
|
||||||
<!-- TODO: replace editor content with tiptap render view -->
|
<div class="content hyphenate-text">{{ excerpt }}</div>
|
||||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
||||||
<div class="content hyphenate-text" v-html="excerpt" />
|
|
||||||
<footer
|
<footer
|
||||||
class="footer"
|
class="footer"
|
||||||
v-observe-visibility="(isVisible, entry) => visibilityChanged(isVisible, entry, post.id)"
|
v-observe-visibility="(isVisible, entry) => visibilityChanged(isVisible, entry, post.id)"
|
||||||
@ -232,7 +230,7 @@ export default {
|
|||||||
user: 'auth/user',
|
user: 'auth/user',
|
||||||
}),
|
}),
|
||||||
excerpt() {
|
excerpt() {
|
||||||
return this.$filters.removeLinks(this.post.contentExcerpt)
|
return this.$filters.removeHtml(this.post.content)
|
||||||
},
|
},
|
||||||
isAuthor() {
|
isAuthor() {
|
||||||
const { author } = this.post
|
const { author } = this.post
|
||||||
@ -399,6 +397,10 @@ export default {
|
|||||||
.content {
|
.content {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
margin-bottom: $space-small;
|
margin-bottom: $space-small;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 6;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
|
|||||||
@ -90,7 +90,7 @@ export default {
|
|||||||
name:
|
name:
|
||||||
report.resource.name ||
|
report.resource.name ||
|
||||||
this.$filters.truncate(report.resource.title, 30) ||
|
this.$filters.truncate(report.resource.title, 30) ||
|
||||||
this.$filters.truncate(this.$filters.removeHtml(report.resource.contentExcerpt), 30),
|
this.$filters.truncate(this.$filters.removeHtml(report.resource.content), 30),
|
||||||
},
|
},
|
||||||
buttons: {
|
buttons: {
|
||||||
confirm: {
|
confirm: {
|
||||||
|
|||||||
@ -153,9 +153,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
linkText() {
|
linkText() {
|
||||||
return (
|
return this.report.resource.title || this.$filters.removeHtml(this.report.resource.content)
|
||||||
this.report.resource.title || this.$filters.removeHtml(this.report.resource.contentExcerpt)
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
statusIconName() {
|
statusIconName() {
|
||||||
return this.isDisabled ? this.icons.eyeSlash : this.icons.eye
|
return this.isDisabled ? this.icons.eyeSlash : this.icons.eye
|
||||||
|
|||||||
@ -7,7 +7,7 @@ export const notifications = [
|
|||||||
id: 'post-1',
|
id: 'post-1',
|
||||||
title: 'some post title',
|
title: 'some post title',
|
||||||
slug: 'some-post-title',
|
slug: 'some-post-title',
|
||||||
contentExcerpt: 'this is a post content',
|
content: 'this is a post content',
|
||||||
author: {
|
author: {
|
||||||
id: 'john-1',
|
id: 'john-1',
|
||||||
slug: 'john-doe',
|
slug: 'john-doe',
|
||||||
@ -21,12 +21,12 @@ export const notifications = [
|
|||||||
from: {
|
from: {
|
||||||
__typename: 'Comment',
|
__typename: 'Comment',
|
||||||
id: 'comment-2',
|
id: 'comment-2',
|
||||||
contentExcerpt: 'this is yet another post content',
|
content: 'this is yet another post content',
|
||||||
post: {
|
post: {
|
||||||
id: 'post-1',
|
id: 'post-1',
|
||||||
title: 'some post on a comment',
|
title: 'some post on a comment',
|
||||||
slug: 'some-post-on-a-comment',
|
slug: 'some-post-on-a-comment',
|
||||||
contentExcerpt: 'this is a post content',
|
content: 'this is a post content',
|
||||||
author: {
|
author: {
|
||||||
id: 'john-1',
|
id: 'john-1',
|
||||||
slug: 'john-doe',
|
slug: 'john-doe',
|
||||||
|
|||||||
@ -9,7 +9,7 @@ export default () => {
|
|||||||
mutation ($postId: ID!, $content: String!) {
|
mutation ($postId: ID!, $content: String!) {
|
||||||
CreateComment(postId: $postId, content: $content) {
|
CreateComment(postId: $postId, content: $content) {
|
||||||
id
|
id
|
||||||
contentExcerpt
|
|
||||||
content
|
content
|
||||||
createdAt
|
createdAt
|
||||||
updatedAt
|
updatedAt
|
||||||
@ -45,7 +45,7 @@ export default () => {
|
|||||||
mutation ($content: String!, $id: ID!) {
|
mutation ($content: String!, $id: ID!) {
|
||||||
UpdateComment(content: $content, id: $id) {
|
UpdateComment(content: $content, id: $id) {
|
||||||
id
|
id
|
||||||
contentExcerpt
|
|
||||||
content
|
content
|
||||||
createdAt
|
createdAt
|
||||||
updatedAt
|
updatedAt
|
||||||
@ -70,7 +70,7 @@ export default () => {
|
|||||||
mutation ($id: ID!) {
|
mutation ($id: ID!) {
|
||||||
DeleteComment(id: $id) {
|
DeleteComment(id: $id) {
|
||||||
id
|
id
|
||||||
contentExcerpt
|
|
||||||
content
|
content
|
||||||
createdAt
|
createdAt
|
||||||
disabled
|
disabled
|
||||||
|
|||||||
@ -8,7 +8,7 @@ export default () => {
|
|||||||
query Comment($postId: ID) {
|
query Comment($postId: ID) {
|
||||||
Comment(postId: $postId) {
|
Comment(postId: $postId) {
|
||||||
id
|
id
|
||||||
contentExcerpt
|
content
|
||||||
createdAt
|
createdAt
|
||||||
author {
|
author {
|
||||||
id
|
id
|
||||||
|
|||||||
@ -42,7 +42,7 @@ export const reportsListQuery = () => {
|
|||||||
}
|
}
|
||||||
... on Comment {
|
... on Comment {
|
||||||
id
|
id
|
||||||
contentExcerpt
|
content
|
||||||
disabled
|
disabled
|
||||||
deleted
|
deleted
|
||||||
author {
|
author {
|
||||||
|
|||||||
@ -32,7 +32,7 @@ export default () => {
|
|||||||
slug
|
slug
|
||||||
title
|
title
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
language
|
language
|
||||||
image {
|
image {
|
||||||
...imageUrls
|
...imageUrls
|
||||||
@ -83,7 +83,7 @@ export default () => {
|
|||||||
title
|
title
|
||||||
slug
|
slug
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
language
|
language
|
||||||
image {
|
image {
|
||||||
...imageUrls
|
...imageUrls
|
||||||
@ -146,7 +146,7 @@ export default () => {
|
|||||||
title
|
title
|
||||||
slug
|
slug
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
language
|
language
|
||||||
pinnedBy {
|
pinnedBy {
|
||||||
id
|
id
|
||||||
@ -163,7 +163,7 @@ export default () => {
|
|||||||
title
|
title
|
||||||
slug
|
slug
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
language
|
language
|
||||||
pinnedBy {
|
pinnedBy {
|
||||||
id
|
id
|
||||||
@ -180,7 +180,7 @@ export default () => {
|
|||||||
title
|
title
|
||||||
slug
|
slug
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
language
|
language
|
||||||
pinnedBy {
|
pinnedBy {
|
||||||
id
|
id
|
||||||
@ -197,7 +197,7 @@ export default () => {
|
|||||||
title
|
title
|
||||||
slug
|
slug
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
language
|
language
|
||||||
pinnedBy {
|
pinnedBy {
|
||||||
id
|
id
|
||||||
@ -214,7 +214,7 @@ export default () => {
|
|||||||
title
|
title
|
||||||
slug
|
slug
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
language
|
language
|
||||||
pinnedBy {
|
pinnedBy {
|
||||||
id
|
id
|
||||||
@ -231,7 +231,7 @@ export default () => {
|
|||||||
title
|
title
|
||||||
slug
|
slug
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
language
|
language
|
||||||
pinnedBy {
|
pinnedBy {
|
||||||
id
|
id
|
||||||
|
|||||||
@ -8,7 +8,6 @@ export const comment = gql`
|
|||||||
disabled
|
disabled
|
||||||
deleted
|
deleted
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
isPostObservedByMe
|
isPostObservedByMe
|
||||||
postObservingUsersCount
|
postObservingUsersCount
|
||||||
shoutedByCurrentUser
|
shoutedByCurrentUser
|
||||||
|
|||||||
@ -8,7 +8,6 @@ export const post = gql`
|
|||||||
id
|
id
|
||||||
title
|
title
|
||||||
content
|
content
|
||||||
contentExcerpt
|
|
||||||
createdAt
|
createdAt
|
||||||
updatedAt
|
updatedAt
|
||||||
sortDate
|
sortDate
|
||||||
|
|||||||
@ -434,7 +434,7 @@ export default {
|
|||||||
id: post.id,
|
id: post.id,
|
||||||
slug: post.slug,
|
slug: post.slug,
|
||||||
name: post.title,
|
name: post.title,
|
||||||
description: post.contentExcerpt,
|
description: this.$filters.removeHtml(post.content),
|
||||||
},
|
},
|
||||||
geometry: {
|
geometry: {
|
||||||
type: 'Point',
|
type: 'Point',
|
||||||
|
|||||||
@ -87,11 +87,26 @@ export default ({ app = {} }) => {
|
|||||||
if (!content) return ''
|
if (!content) return ''
|
||||||
let contentExcerpt = content
|
let contentExcerpt = content
|
||||||
if (replaceLinebreaks) {
|
if (replaceLinebreaks) {
|
||||||
// replace linebreaks with spaces first
|
// replace linebreaks and block-level closing tags with spaces
|
||||||
contentExcerpt = contentExcerpt.replace(/<br>/gim, ' ').trim()
|
contentExcerpt = contentExcerpt
|
||||||
|
.replace(/<\/(p|h[1-6]|li|div|blockquote)>/gim, ' ')
|
||||||
|
.replace(/<br\s*\/?>/gim, ' ')
|
||||||
|
.trim()
|
||||||
}
|
}
|
||||||
// remove the rest of the HTML
|
// remove the rest of the HTML
|
||||||
contentExcerpt = contentExcerpt.replace(/<(?:.|\n)*?>/gm, '').trim()
|
contentExcerpt = contentExcerpt.replace(/<(?:.|\n)*?>/gm, '').trim()
|
||||||
|
// normalize multiple spaces into one
|
||||||
|
contentExcerpt = contentExcerpt.replace(/ {2,}/g, ' ')
|
||||||
|
// decode common HTML entities
|
||||||
|
const entities = {
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
'"': '"',
|
||||||
|
''': "'",
|
||||||
|
' ': ' ',
|
||||||
|
}
|
||||||
|
contentExcerpt = contentExcerpt.replace(/&(?:amp|lt|gt|quot|#39|nbsp);/g, (m) => entities[m])
|
||||||
|
|
||||||
return contentExcerpt
|
return contentExcerpt
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user