Merge pull request #1399 from Human-Connection/1395-hashtags-imported-with-not-allowed-chars

🍰 Correct the import of tags from the Alpha and refactor editor hashtags
This commit is contained in:
mattwr18 2019-09-04 17:05:12 +02:00 committed by GitHub
commit d81bbec00a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 54 additions and 19 deletions

View File

@ -100,6 +100,7 @@
"slug": "~1.1.0",
"trunc-html": "~1.1.2",
"uuid": "~3.3.3",
"xregexp": "^4.2.4",
"wait-on": "~3.3.0"
},
"devDependencies": {
@ -130,4 +131,4 @@
"prettier": "~1.18.2",
"supertest": "~4.0.2"
}
}
}

View File

@ -1,17 +1,18 @@
import cheerio from 'cheerio'
import { exec, build } from 'xregexp/xregexp-all.js'
// formats of a Hashtag:
// https://en.wikipedia.org/w/index.php?title=Hashtag&oldid=905141980#Style
// here:
// 0. Search for whole string.
// 1. Hashtag has only 'a-z', 'A-Z', and '0-9'.
// 2. If it starts with a digit '0-9' than 'a-z', or 'A-Z' has to follow.
const ID_REGEX = /^\/search\/hashtag\/(([a-zA-Z]+[a-zA-Z0-9]*)|([0-9]+[a-zA-Z]+[a-zA-Z0-9]*))$/g
// 1. Hashtag has only all unicode characters and '0-9'.
// 2. If it starts with a digit '0-9' than a unicode character has to follow.
const regX = build('^/search/hashtag/((\\pL+[\\pL0-9]*)|([0-9]+\\pL+[\\pL0-9]*))$')
export default function(content) {
if (!content) return []
const $ = cheerio.load(content)
// We can not search for class '.hashtag', because the classes are removed at the 'xss' middleware.
// But we have to know, which Hashtags are removed from the content es well, so we search for the 'a' html-tag.
// But we have to know, which Hashtags are removed from the content as well, so we search for the 'a' html-tag.
const urls = $('a')
.map((_, el) => {
return $(el).attr('href')
@ -19,8 +20,8 @@ export default function(content) {
.get()
const hashtags = []
urls.forEach(url => {
let match
while ((match = ID_REGEX.exec(url)) != null) {
const match = exec(url, regX)
if (match != null) {
hashtags.push(match[1])
}
})

View File

@ -28,9 +28,14 @@ describe('extractHashtags', () => {
})
it('ignores Hashtag links with not allowed character combinations', () => {
// Allowed are all unicode letters '\pL' and all digits '0-9'. There haveto be at least one letter in it.
const content =
'<p>Something inspirational about <a href="/search/hashtag/AbcDefXyz0123456789!*(),2" class="hashtag" target="_blank">#AbcDefXyz0123456789!*(),2</a>, <a href="/search/hashtag/0123456789" class="hashtag" target="_blank">#0123456789</a>, <a href="/search/hashtag/0123456789a" class="hashtag" target="_blank">#0123456789a</a> and <a href="/search/hashtag/AbcDefXyz0123456789" target="_blank">#AbcDefXyz0123456789</a>.</p>'
expect(extractHashtags(content)).toEqual(['0123456789a', 'AbcDefXyz0123456789'])
'<p>Something inspirational about <a href="/search/hashtag/AbcDefXyz0123456789!*(),2" class="hashtag" target="_blank">#AbcDefXyz0123456789!*(),2</a>, <a href="/search/hashtag/0123456789" class="hashtag" target="_blank">#0123456789</a>, <a href="/search/hashtag/0123456789a" class="hashtag" target="_blank">#0123456789a</a>, <a href="/search/hashtag/AbcDefXyz0123456789" target="_blank">#AbcDefXyz0123456789</a>, and <a href="/search/hashtag/λαπ" target="_blank">#λαπ</a>.</p>'
expect(extractHashtags(content).sort()).toEqual([
'0123456789a',
'AbcDefXyz0123456789',
'λαπ',
])
})
})

View File

@ -681,7 +681,7 @@
pirates "^4.0.0"
source-map-support "^0.5.9"
"@babel/runtime-corejs2@^7.5.5":
"@babel/runtime-corejs2@^7.2.0", "@babel/runtime-corejs2@^7.5.5":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.5.5.tgz#c3214c08ef20341af4187f1c9fbdc357fbec96b2"
integrity sha512-FYATQVR00NSNi7mUfpPDp7E8RYMXDuO8gaix7u/w3GekfUinKgX1AcTxs7SoiEmoEW9mbpjrwqWSW6zCmw5h8A==
@ -8862,6 +8862,13 @@ xmldom@0.1.19:
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.19.tgz#631fc07776efd84118bf25171b37ed4d075a0abc"
integrity sha1-Yx/Ad3bv2EEYvyUXGzftTQdaCrw=
xregexp@^4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.2.4.tgz#02a4aea056d65a42632c02f0233eab8e4d7e57ed"
integrity sha512-sO0bYdYeJAJBcJA8g7MJJX7UrOZIfJPd8U2SC7B2Dd/J24U0aQNoGp33shCaBSWeb0rD5rh6VBUIXOkGal1TZA==
dependencies:
"@babel/runtime-corejs2" "^7.2.0"
xtend@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"

View File

@ -125,7 +125,6 @@
[ ] wasSeeded: { type: Boolean }
}
*/
CALL apoc.load.json("file:${IMPORT_CHUNK_PATH_CQL_FILE}") YIELD value as post
MERGE (p:Post {id: post._id["$oid"]})
ON CREATE SET
@ -148,6 +147,10 @@ MATCH (c:Category {id: categoryId})
MERGE (p)-[:CATEGORIZED]->(c)
WITH p, post.tags AS tags
UNWIND tags AS tag
MERGE (t:Tag {id: apoc.text.clean(tag), disabled: false, deleted: false})
WITH apoc.text.replace(tag, '[^\\p{L}0-9]', '') as tagNoSpacesAllowed
CALL apoc.when(tagNoSpacesAllowed =~ '^((\\p{L}+[\\p{L}0-9]*)|([0-9]+\\p{L}+[\\p{L}0-9]*))$', 'RETURN tagNoSpacesAllowed', '', {tagNoSpacesAllowed: tagNoSpacesAllowed})
YIELD value as validated
WHERE validated.tagNoSpacesAllowed IS NOT NULL
MERGE (t:Tag { id: validated.tagNoSpacesAllowed, disabled: false, deleted: false })
MERGE (p)-[:TAGGED]->(t)
;

View File

@ -26,6 +26,7 @@ import { Editor, EditorContent } from 'tiptap'
import { History } from 'tiptap-extensions'
import linkify from 'linkify-it'
import stringHash from 'string-hash'
import { replace, build } from 'xregexp/xregexp-all.js'
import * as key from '../../constants/keycodes'
import { HASHTAG, MENTION } from '../../constants/editor'
@ -214,8 +215,9 @@ export default {
},
sanitizeQuery(query) {
if (this.suggestionType === HASHTAG) {
// remove all not allowed chars
query = query.replace(/[^a-zA-Z0-9]/gm, '')
// remove all non unicode letters and non digits
const regexMatchAllNonUnicodeLettersOrDigits = build('[^\\pL0-9]')
query = replace(query, regexMatchAllNonUnicodeLettersOrDigits, '', 'all')
// if the query is only made of digits, make it empty
return query.replace(/[0-9]/gm, '') === '' ? '' : query
}

View File

@ -7,15 +7,15 @@
:class="{ 'is-selected': navigatedItemIndex === index }"
@click="selectItem(item)"
>
{{ createItemLabel(item) }}
{{ createItemLabel(item) | truncate(50) }}
</li>
<template v-if="isHashtag">
<li v-if="!query" class="suggestion-list__item hint">
{{ $t('editor.hashtag.addLetter') }}
</li>
<li v-if="!query" class="suggestion-list__item hint">{{ $t('editor.hashtag.addLetter') }}</li>
<template v-else-if="!filteredItems.find(el => el.id === query)">
<li class="suggestion-list__item hint">{{ $t('editor.hashtag.addHashtag') }}</li>
<li class="suggestion-list__item" @click="selectItem({ id: query })">#{{ query }}</li>
<li class="suggestion-list__item" @click="selectItem({ id: query })">
#{{ query | truncate(50) }}
</li>
</template>
</template>
<template v-else-if="isMention">

View File

@ -81,6 +81,7 @@
"vue-izitoast": "^1.2.1",
"vue-sweetalert-icons": "~4.2.0",
"vuex-i18n": "~1.13.1",
"xregexp": "^4.2.4",
"zxcvbn": "^4.4.2"
},
"devDependencies": {

View File

@ -742,6 +742,14 @@
js-levenshtein "^1.1.3"
semver "^5.5.0"
"@babel/runtime-corejs2@^7.2.0":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.5.5.tgz#c3214c08ef20341af4187f1c9fbdc357fbec96b2"
integrity sha512-FYATQVR00NSNi7mUfpPDp7E8RYMXDuO8gaix7u/w3GekfUinKgX1AcTxs7SoiEmoEW9mbpjrwqWSW6zCmw5h8A==
dependencies:
core-js "^2.6.5"
regenerator-runtime "^0.13.2"
"@babel/runtime@7.3.4":
version "7.3.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83"
@ -15734,6 +15742,13 @@ xml-name-validator@^3.0.0:
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
xregexp@^4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.2.4.tgz#02a4aea056d65a42632c02f0233eab8e4d7e57ed"
integrity sha512-sO0bYdYeJAJBcJA8g7MJJX7UrOZIfJPd8U2SC7B2Dd/J24U0aQNoGp33shCaBSWeb0rD5rh6VBUIXOkGal1TZA==
dependencies:
"@babel/runtime-corejs2" "^7.2.0"
xtend@^4.0.0, xtend@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"