-
+
Report
@@ -140,6 +145,7 @@
v-if="githubUrl"
:href="githubUrl"
:target="$external()"
+ rel="noopener noreferrer nofollow"
class="sidebar__item github-button iconified-button"
>
@@ -209,7 +215,7 @@
:key="project.id"
:name="project.title"
:display="$cosmetics.searchDisplayMode.user"
- :gallery-images="
+ :featured-image="
project.gallery
.slice()
.sort((a, b) => b.featured - a.featured)
diff --git a/plugins/markdown.js b/plugins/markdown.js
new file mode 100644
index 00000000..b71b7b5d
--- /dev/null
+++ b/plugins/markdown.js
@@ -0,0 +1,23 @@
+import MarkdownIt from 'markdown-it'
+
+export default (ctx, inject) => {
+ const md = new MarkdownIt('default', {
+ html: true,
+ linkify: true,
+ breaks: false,
+ })
+
+ const defaultRender =
+ md.renderer.rules.link_open ||
+ function (tokens, idx, options, env, self) {
+ return self.renderToken(tokens, idx, options)
+ }
+
+ md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
+ tokens[idx].attrJoin('rel', 'noopener noreferrer ugc')
+
+ return defaultRender(tokens, idx, options, env, self)
+ }
+
+ inject('md', md)
+}
diff --git a/plugins/shorthands.js b/plugins/shorthands.js
index 26bc9f1f..befbcf5e 100644
--- a/plugins/shorthands.js
+++ b/plugins/shorthands.js
@@ -32,116 +32,33 @@ export default (ctx, inject) => {
inject('formatCategory', formatCategory)
inject('formatCategoryHeader', formatCategoryHeader)
inject('computeVersions', (versions) => {
- const versionsMap = {}
-
- for (const version of versions.sort(
- (a, b) => ctx.$dayjs(a.date_published) - ctx.$dayjs(b.date_published)
- )) {
- if (versionsMap[version.version_number]) {
- versionsMap[version.version_number].push(version)
- } else {
- versionsMap[version.version_number] = [version]
- }
- }
-
+ const visitedVersions = []
const returnVersions = []
- for (const id in versionsMap) {
- const versions = versionsMap[id]
-
- if (versions.length === 1) {
- versions[0].displayUrlEnding = versions[0].version_number
-
- returnVersions.push(versions[0])
+ for (const version of versions.reverse()) {
+ if (visitedVersions.includes(version.version_number)) {
+ visitedVersions.push(version.version_number)
+ version.displayUrlEnding = version.id
} else {
- const reservedNames = {}
-
- const seenLoaders = {}
- const duplicateLoaderIndexes = []
-
- for (let i = 0; i < versions.length; i++) {
- const version = versions[i]
- const value = version.loaders.join('+')
-
- if (seenLoaders[value]) {
- duplicateLoaderIndexes.push(i)
- } else {
- if (i !== 0) {
- version.displayUrlEnding = `${version.version_number}-${value}`
- } else {
- version.displayUrlEnding = version.version_number
- }
-
- reservedNames[version.displayUrlEnding] = true
-
- version.displayName = version.loaders
- .map((x) => x.charAt(0).toUpperCase() + x.slice(1))
- .join(', ')
-
- returnVersions.push(version)
-
- seenLoaders[value] = true
- }
- }
-
- const seenGameVersions = {}
- const duplicateGameVersionIndexes = []
-
- for (const i of duplicateLoaderIndexes) {
- const version = versions[i]
- const value = version.game_versions.join('+')
-
- if (seenGameVersions[value]) {
- duplicateGameVersionIndexes.push(i)
- } else {
- if (i !== 0) {
- let setDisplayUrl = false
-
- for (const gameVersion in version.game_versions) {
- const displayUrlEnding = `${version.version_number}-${gameVersion}`
-
- if (!reservedNames[version.version_number]) {
- version.displayUrlEnding = displayUrlEnding
- reservedNames[displayUrlEnding] = true
- setDisplayUrl = true
-
- break
- }
- }
-
- if (!setDisplayUrl) {
- version.displayUrlEnding = `${version.version_number}-${value}`
- }
- } else if (!reservedNames[version.version_number]) {
- version.displayUrlEnding = version.version_number
- reservedNames[version.version_number] = true
- }
-
- version.displayName = formatVersions(
- version.game_versions,
- ctx.store
- )
-
- returnVersions.push(version)
-
- seenGameVersions[value] = true
- }
- }
-
- for (const i in duplicateGameVersionIndexes) {
- const version = versions[i]
-
- version.displayUrlEnding = version.id
- version.displayName = version.id
-
- returnVersions.push(version)
- }
+ visitedVersions.push(version.version_number)
+ version.displayUrlEnding = version.version_number
}
+
+ returnVersions.push(version)
}
- return returnVersions.sort(
- (a, b) => ctx.$dayjs(b.date_published) - ctx.$dayjs(a.date_published)
- )
+ return returnVersions.reverse().map((version, index) => {
+ const nextVersion = returnVersions[index + 1]
+ if (
+ nextVersion &&
+ version.changelog &&
+ nextVersion.changelog === version.changelog
+ ) {
+ return { duplicate: true, ...version }
+ } else {
+ return { duplicate: false, ...version }
+ }
+ })
})
inject('getProjectTypeForDisplay', (type, categories) => {
if (type === 'mod') {
diff --git a/plugins/xss.js b/plugins/xss.js
index 1d826f38..4e5a702a 100644
--- a/plugins/xss.js
+++ b/plugins/xss.js
@@ -17,6 +17,7 @@ const options = {
input: ['checked', 'disabled', 'type'],
iframe: ['width', 'height', 'allowfullscreen', 'frameborder'],
img: [...xss.whiteList.img, 'style'],
+ a: [...xss.whiteList.a, 'rel'],
},
css: {
whiteList: {
diff --git a/static/robots.txt b/static/robots.txt
new file mode 100644
index 00000000..e93bd2db
--- /dev/null
+++ b/static/robots.txt
@@ -0,0 +1,3 @@
+User-agent: *
+Disallow:
+Sitemap: https://modrinth.com/sitemap.xml