Ocelot-Social/webapp/plugins/vue-filters.js

124 lines
3.7 KiB
JavaScript

import Vue from 'vue'
import format from 'date-fns/format'
import accounting from 'accounting'
import trunc from 'trunc-html'
import { getDateFnsLocale } from '~/locales'
export default ({ app = {} }) => {
app.$filters = Object.assign(app.$filters || {}, {
date: (value, fmt = 'dd. MMM yyyy') => {
if (!value) return ''
return format(new Date(value), fmt, {
locale: getDateFnsLocale(app),
})
},
dateTime: (value, fmt = 'dd. MMM yyyy HH:mm') => {
if (!value) return ''
return format(new Date(value), fmt, {
locale: getDateFnsLocale(app),
})
},
number: (value, precision = 2, thousands = '.', decimals = ',', fallback = null) => {
if (isNaN(value) && fallback) {
return fallback
}
return accounting.formatNumber(value || 0, precision, thousands, decimals)
},
// doesn't truncate in the middle of words
truncate: (value = '', length = -1) => {
if (!value || typeof value !== 'string' || value.length <= 0) {
return ''
}
if (length <= 0) {
return value
}
return trunc(value, length).html
},
// truncates in the middle of words
truncateStr: (value = '', length = -1) => {
if (!value || typeof value !== 'string' || value.length <= 0) {
return ''
}
if (length <= 0) {
return value
}
if (length < value.length) {
return value.substring(0, length) + '…'
}
return value
},
list: (value, glue = ', ', truncate = 0) => {
if (!Array.isArray(value) || !value.length) {
return ''
}
if (truncate > 0) {
value = value.map((item) => {
return app.$filters.truncate(item, truncate)
})
}
return value.join(glue)
},
listByKey: (values, key, glue, truncate) => {
return app.$filters.list(
values.map((item) => item[key]),
glue,
truncate,
)
},
camelCase: (value = '') => {
return value
.replace(/(?:^\w|[A-Za-z]|\b\w)/g, (letter, index) => {
return index === 0 ? letter.toUpperCase() : letter.toLowerCase()
})
.replace(/\s+/g, '')
},
removeLinks: (content) => {
if (!content) return ''
// remove all links from excerpt to prevent issues with the surrounding link
let excerpt = content.replace(/<a.*>(.+)<\/a>/gim, '$1')
// do not display content that is only linebreaks
if (excerpt.replace(/<br>/gim, '').trim() === '') {
excerpt = ''
}
return excerpt
},
removeHtml: (content, replaceLinebreaks = true) => {
if (!content) return ''
let contentExcerpt = content
if (replaceLinebreaks) {
// replace linebreaks and block-level closing tags with spaces
contentExcerpt = contentExcerpt
.replace(/<\/(p|h[1-6]|li|div|blockquote)>/gim, ' ')
.replace(/<br\s*\/?>/gim, ' ')
.trim()
}
// remove the rest of the HTML
contentExcerpt = contentExcerpt.replace(/<(?:.|\n)*?>/gm, '').trim()
// normalize multiple spaces into one
contentExcerpt = contentExcerpt.replace(/ {2,}/g, ' ')
// decode common HTML entities
const entities = {
'&amp;': '&',
'&lt;': '<',
'&gt;': '>',
'&quot;': '"',
'&#39;': "'",
'&nbsp;': ' ',
}
contentExcerpt = contentExcerpt.replace(/&(?:amp|lt|gt|quot|#39|nbsp);/g, (m) => entities[m])
return contentExcerpt
},
})
// add all methods as filters on each vue component
Object.keys(app.$filters).forEach((key) => {
Vue.filter(key, app.$filters[key])
})
Vue.prototype.$filters = app.$filters
return app
}