diff --git a/.eslintignore b/.eslintignore
index db0300d396..27b2a4722b 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -867,6 +867,9 @@ packages/lib/Synchronizer.js.map
packages/lib/TaskQueue.d.ts
packages/lib/TaskQueue.js
packages/lib/TaskQueue.js.map
+packages/lib/array.d.ts
+packages/lib/array.js
+packages/lib/array.js.map
packages/lib/commands/historyBackward.d.ts
packages/lib/commands/historyBackward.js
packages/lib/commands/historyBackward.js.map
diff --git a/.gitignore b/.gitignore
index 2aa5a343a9..a655bb7a2b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -852,6 +852,9 @@ packages/lib/Synchronizer.js.map
packages/lib/TaskQueue.d.ts
packages/lib/TaskQueue.js
packages/lib/TaskQueue.js.map
+packages/lib/array.d.ts
+packages/lib/array.js
+packages/lib/array.js.map
packages/lib/commands/historyBackward.d.ts
packages/lib/commands/historyBackward.js
packages/lib/commands/historyBackward.js.map
diff --git a/Assets/WebsiteAssets/images/sponsors/HostingDe.png b/Assets/WebsiteAssets/images/sponsors/HostingDe.png
new file mode 100644
index 0000000000..c381da40c6
Binary files /dev/null and b/Assets/WebsiteAssets/images/sponsors/HostingDe.png differ
diff --git a/README.md b/README.md
index de45c1e71d..c7a356555b 100644
--- a/README.md
+++ b/README.md
@@ -64,19 +64,21 @@ The Web Clipper is a browser extension that allows you to save web pages and scr
# Sponsors
-
+
+
+
* * *
-
+
| | | | |
| :---: | :---: | :---: | :---: |
| [avanderberg](https://github.com/avanderberg) | [c-nagy](https://github.com/c-nagy) | [cabottech](https://github.com/cabottech) | [chr15m](https://github.com/chr15m) |
-| [chrootlogin](https://github.com/chrootlogin) | [dbrandonjohnson](https://github.com/dbrandonjohnson) | [fbloise](https://github.com/fbloise) | [h4sh5](https://github.com/h4sh5) |
-| [Jesssullivan](https://github.com/Jesssullivan) | [joesfer](https://github.com/joesfer) | [konishi-t](https://github.com/konishi-t) | [maxtruxa](https://github.com/maxtruxa) |
-| [mcejp](https://github.com/mcejp) | [nicholashead](https://github.com/nicholashead) | [piccobit](https://github.com/piccobit) | [ravenscroftj](https://github.com/ravenscroftj) |
-| [thismarty](https://github.com/thismarty) | [thomasbroussard](https://github.com/thomasbroussard) | | |
-
+| [chrootlogin](https://github.com/chrootlogin) | [clmntsl](https://github.com/clmntsl) | [dbrandonjohnson](https://github.com/dbrandonjohnson) | [fbloise](https://github.com/fbloise) |
+| [h4sh5](https://github.com/h4sh5) | [Jesssullivan](https://github.com/Jesssullivan) | [joesfer](https://github.com/joesfer) | [konishi-t](https://github.com/konishi-t) |
+| [maxtruxa](https://github.com/maxtruxa) | [mcejp](https://github.com/mcejp) | [nicholashead](https://github.com/nicholashead) | [piccobit](https://github.com/piccobit) |
+| [ravenscroftj](https://github.com/ravenscroftj) | [thismarty](https://github.com/thismarty) | [thomasbroussard](https://github.com/thomasbroussard) | |
+
# Table of contents
diff --git a/docs/images/sponsors/HostingDe.png b/docs/images/sponsors/HostingDe.png
new file mode 100644
index 0000000000..c381da40c6
Binary files /dev/null and b/docs/images/sponsors/HostingDe.png differ
diff --git a/packages/lib/ArrayUtils.js b/packages/lib/ArrayUtils.js
index ba1956aaea..4cb96d6830 100644
--- a/packages/lib/ArrayUtils.js
+++ b/packages/lib/ArrayUtils.js
@@ -80,4 +80,15 @@ ArrayUtils.mergeOverlappingIntervals = function(intervals, limit) {
return stack;
};
+ArrayUtils.shuffle = function(array) {
+ array = array.slice();
+ for (let i = array.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ const temp = array[i];
+ array[i] = array[j];
+ array[j] = temp;
+ }
+ return array;
+};
+
module.exports = ArrayUtils;
diff --git a/packages/lib/array.ts b/packages/lib/array.ts
new file mode 100644
index 0000000000..80fd3c3992
--- /dev/null
+++ b/packages/lib/array.ts
@@ -0,0 +1,16 @@
+export function shuffle(array: T[]): T[] {
+ array = array.slice();
+ for (let i = array.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ const temp = array[i];
+ array[i] = array[j];
+ array[j] = temp;
+ }
+ return array;
+}
+
+export function unique(array: T[]): T[] {
+ return array.filter(function(elem, index, self) {
+ return index === self.indexOf(elem);
+ });
+}
diff --git a/packages/tools/sponsors.json b/packages/tools/sponsors.json
index daa4e9097a..9b7d5d8925 100644
--- a/packages/tools/sponsors.json
+++ b/packages/tools/sponsors.json
@@ -71,6 +71,10 @@
{
"name": "konishi-t",
"id": "24908652"
+ },
+ {
+ "name": "clmntsl",
+ "id": "82579431"
}
],
"orgs": [
@@ -88,6 +92,12 @@
"url": "https://tranio.com/italy/",
"title": "Tranio",
"imageName": "Tranio.png"
+ },
+ {
+ "url": "https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-github&mtm_medium=banner",
+ "urlWebsite": "https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-webseite&mtm_medium=banner",
+ "title": "Hosting.de",
+ "imageName": "HostingDe.png"
}
]
}
\ No newline at end of file
diff --git a/packages/tools/update-readme-sponsors.ts b/packages/tools/update-readme-sponsors.ts
index 10b89c9ec7..a9f1bfd7e1 100644
--- a/packages/tools/update-readme-sponsors.ts
+++ b/packages/tools/update-readme-sponsors.ts
@@ -1,17 +1,15 @@
import { readFile } from 'fs-extra';
import { insertContentIntoFile, rootDir } from './tool-utils';
import markdownUtils, { MarkdownTableHeader, MarkdownTableJustify, MarkdownTableRow } from '@joplin/lib/markdownUtils';
+const ArrayUtils = require('@joplin/lib/ArrayUtils');
+const { escapeHtml } = require('@joplin/lib/string-utils');
+import { GithubSponsor, OrgSponsor, Sponsors } from './website/utils/types';
const readmePath = `${rootDir}/README.md`;
const sponsorsPath = `${rootDir}/packages/tools/sponsors.json`;
-interface Sponsor {
- name: string;
- id: string;
-}
-
-async function main() {
- const sponsors: Sponsor[] = (JSON.parse(await readFile(sponsorsPath, 'utf8'))).github;
+async function createGitHubSponsorTable(sponsors: GithubSponsor[]): Promise {
+ sponsors = sponsors.slice();
sponsors.sort((a, b) => {
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : +1;
@@ -49,13 +47,36 @@ async function main() {
if (!sponsor) break;
}
- const mdTable = markdownUtils.createMarkdownTable(headers, rows);
+ return markdownUtils.createMarkdownTable(headers, rows);
+}
+
+async function createOrgSponsorTable(sponsors: OrgSponsor[]): Promise {
+ sponsors = ArrayUtils.shuffle(sponsors);
+
+ const output: string[] = [];
+
+ for (const sponsor of sponsors) {
+ output.push(``);
+ }
+
+ return output.join(' ');
+}
+
+async function main() {
+ const sponsors: Sponsors = JSON.parse(await readFile(sponsorsPath, 'utf8'));
await insertContentIntoFile(
readmePath,
- '\n',
- '\n',
- mdTable
+ '\n',
+ '\n',
+ await createGitHubSponsorTable(sponsors.github)
+ );
+
+ await insertContentIntoFile(
+ readmePath,
+ '\n',
+ '\n',
+ await createOrgSponsorTable(sponsors.orgs)
);
}
diff --git a/packages/tools/website/build.ts b/packages/tools/website/build.ts
index 7cdd003f30..af4a3d4727 100644
--- a/packages/tools/website/build.ts
+++ b/packages/tools/website/build.ts
@@ -2,8 +2,9 @@ import * as fs from 'fs-extra';
import { insertContentIntoFile, rootDir } from '../tool-utils';
import { pressCarouselItems } from './utils/pressCarousel';
import { getMarkdownIt, loadMustachePartials, markdownToPageHtml, renderMustache } from './utils/render';
-import { Env, PlanPageParams, Sponsors, TemplateParams } from './utils/types';
+import { Env, OrgSponsor, PlanPageParams, Sponsors, TemplateParams } from './utils/types';
import { getPlans, StripePublicConfig } from '@joplin/lib/utils/joplinCloud';
+import { shuffle } from '@joplin/lib/array';
const dirname = require('path').dirname;
const glob = require('glob');
const path = require('path');
@@ -42,7 +43,6 @@ async function getDonateLinks() {
}
function replaceGitHubByWebsiteLinks(md: string) {
- // let output = md.replace(/https:\/\/github.com\/laurent22\/joplin\/blob\/master\/readme\/(.*?)\/index\.md(#[^\s)]+|)/g, 'https://joplinapp.org/$1');
return md
.replace(/https:\/\/github.com\/laurent22\/joplin\/blob\/dev\/readme\/(.*?)\.md(#[^\s)]+|)/g, '/$1/$2')
.replace(/https:\/\/github.com\/laurent22\/joplin\/blob\/dev\/README\.md(#[^\s)]+|)/g, '/help/$1');
@@ -182,7 +182,13 @@ async function updateDownloadPage(downloadButtonsHtml: Record) {
async function loadSponsors(): Promise {
const sponsorsPath = `${rootDir}/packages/tools/sponsors.json`;
- return JSON.parse(await fs.readFile(sponsorsPath, 'utf8'));
+ const output: Sponsors = JSON.parse(await fs.readFile(sponsorsPath, 'utf8'));
+ output.orgs = shuffle(output.orgs.map(o => {
+ if (o.urlWebsite) o.url = o.urlWebsite;
+ return o;
+ }));
+
+ return output;
}
async function main() {
diff --git a/packages/tools/website/utils/types.ts b/packages/tools/website/utils/types.ts
index 732717d0d7..420516f4e9 100644
--- a/packages/tools/website/utils/types.ts
+++ b/packages/tools/website/utils/types.ts
@@ -5,13 +5,14 @@ export enum Env {
Prod = 'prod',
}
-interface GithubSponsor {
+export interface GithubSponsor {
name: string;
id: string;
}
-interface OrgSponsor {
+export interface OrgSponsor {
url: string;
+ urlWebsite?: string;
title: string;
imageName: string;
}