diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000..3a28822c
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,2 @@
+ko_fi: vpdaspid
+custom: ["https://assetstore.unity.com/packages/package/2333465"]
diff --git a/README.md b/README.md
index 6ec7628a..4039507c 100644
--- a/README.md
+++ b/README.md
@@ -180,4 +180,5 @@ Requires Unity 6000.0.53f1 or newer. If you got the package from the Asset Store
## Support the project
-
+
+
diff --git a/Website/docs/Images/support-card.svg b/Website/docs/Images/support-card.svg
index f07d4fde..f66d6cac 100644
--- a/Website/docs/Images/support-card.svg
+++ b/Website/docs/Images/support-card.svg
@@ -1,6 +1,7 @@
-
- Enjoying Aspid.FastTools? Support on the Asset Store
-
+
+ Enjoying Aspid.FastTools?
+
@@ -14,16 +15,12 @@
.mark { fill: #1d8840; }
.title { fill: #1f2328; }
.text { fill: #59636e; }
- .button { fill: #1d8840; }
- .ink { fill: #ffffff; }
@media (prefers-color-scheme: dark) {
.frame { fill: url(#wash-dark); stroke: url(#frame-dark); }
.badge { fill: #5cb46b; stroke: #5cb46b; }
.mark { fill: #5cb46b; }
.title { fill: #e6edf3; }
.text { fill: #9198a1; }
- .button { fill: #5cb46b; }
- .ink { fill: #06140a; }
}
@@ -31,7 +28,4 @@
Enjoying Aspid.FastTools?
Developed in spare time. Your support keeps it growing.
-
-
- Support on the Asset Store
diff --git a/Website/docs/Images/support-kofi.svg b/Website/docs/Images/support-kofi.svg
new file mode 100644
index 00000000..6bd4eb4e
--- /dev/null
+++ b/Website/docs/Images/support-kofi.svg
@@ -0,0 +1,16 @@
+
+ Support on Ko-fi
+
+
+
+
+
+ Support on Ko-fi
+
diff --git a/Website/docs/Images/support-store.svg b/Website/docs/Images/support-store.svg
new file mode 100644
index 00000000..1ce529bf
--- /dev/null
+++ b/Website/docs/Images/support-store.svg
@@ -0,0 +1,14 @@
+
+ Unity Asset Store
+
+
+
+ Unity Asset Store
+
diff --git a/Website/docs/README.md b/Website/docs/README.md
index 1afd2542..2442c441 100644
--- a/Website/docs/README.md
+++ b/Website/docs/README.md
@@ -140,4 +140,4 @@ Distributed under the [MIT License](https://github.com/VPDPersonal/Aspid.FastToo
## Support the project
-Aspid.FastTools is developed in spare time. If it helps you, support its development on the [Unity Asset Store](https://assetstore.unity.com/packages/package/2333465).
+Aspid.FastTools is developed in spare time. If it helps you, support its development on [Ko-fi](https://ko-fi.com/vpdaspid) or the [Unity Asset Store](https://assetstore.unity.com/packages/package/2333465).
diff --git a/Website/i18n/ru/docusaurus-plugin-content-docs/current/README.md b/Website/i18n/ru/docusaurus-plugin-content-docs/current/README.md
index 236ba8b7..af944e0e 100644
--- a/Website/i18n/ru/docusaurus-plugin-content-docs/current/README.md
+++ b/Website/i18n/ru/docusaurus-plugin-content-docs/current/README.md
@@ -140,4 +140,4 @@ caster.GetDisplayNameWithIndex();
## Поддержать проект
-Aspid.FastTools развивается в свободное время. Если пакет вам помогает, поддержите его развитие в [Unity Asset Store](https://assetstore.unity.com/packages/package/2333465).
+Aspid.FastTools развивается в свободное время. Если пакет вам помогает, поддержите его развитие на [Ko-fi](https://ko-fi.com/vpdaspid) или в [Unity Asset Store](https://assetstore.unity.com/packages/package/2333465).
diff --git a/Website/scripts/github-readme.mjs b/Website/scripts/github-readme.mjs
index 765deee7..6b769df7 100644
--- a/Website/scripts/github-readme.mjs
+++ b/Website/scripts/github-readme.mjs
@@ -10,8 +10,9 @@
* a code preview gives way to the recording of the site's animated preview (`Website/docs/Images/readme-previews`);
* - a section that is only a list of `[Link](…) — summary` items becomes a row of link tiles;
* - the help section becomes the site's call to action (src/components/SupportPanel), without the licence line;
- * - the donation sentence gives way to the image of the site's donation card (src/components/DonatePanel), linking
- * the Asset Store (`Website/docs/Images/support-card.svg`); the sentence becomes its alt text.
+ * - the donation sentence gives way to the image of the site's donation card (src/components/DonatePanel) and a row
+ * of button images under it, one per place: Ko-fi and the Asset Store (`Website/docs/Images/support-*.svg`); the
+ * sentence becomes the card's alt text.
* The README shows only the dark images: a per theme follows the system theme, not GitHub's, so it showed the
* light ones on a dark GitHub page.
* All file URLs are already relative to the README.
@@ -194,20 +195,30 @@ function supportPanel(tree, repository) {
}
/**
- * The donation section: one sentence linking the Asset Store. GitHub cannot style a card, so the sentence gives way to
- * an image of the site's one, linking the store.
+ * The donation section: one sentence linking Ko-fi and the Asset Store. GitHub cannot style a card, and an image links
+ * one place, so the sentence gives way to an image of the site's card, linking the first place, and a row of button
+ * images under it, one per place.
*/
function donateCard(tree, {images, exists}) {
- const isStore = (url) => /^https:\/\/assetstore\.unity\.com\//.test(url);
+ const places = [
+ {test: (url) => /^https:\/\/ko-fi\.com\//.test(url), button: `${images}/support-kofi.svg`, alt: 'Support on Ko-fi'},
+ {test: (url) => /^https:\/\/assetstore\.unity\.com\//.test(url), button: `${images}/support-store.svg`, alt: 'Unity Asset Store'},
+ ];
const card = `${images}/support-card.svg`;
const index = tree.children.findIndex((node, at) => isHeading(node, 2) && tree.children[at + 1]?.type === 'paragraph'
- && tree.children[at + 1].children.some((part) => part.type === 'link' && isStore(part.url))
+ && tree.children[at + 1].children.some((part) => part.type === 'link' && places.some(({test}) => test(part.url)))
&& (!tree.children[at + 2] || tree.children[at + 2].type === 'heading'));
if (index === -1 || !exists(card)) return;
const sentence = tree.children[index + 1].children;
- const store = escape(sentence.find((part) => part.type === 'link' && isStore(part.url)).url);
+ const links = places.flatMap((place) => {
+ const link = sentence.find((part) => part.type === 'link' && place.test(part.url));
+ return link ? [{...place, url: escape(link.url)}] : [];
+ });
const alt = escape(sentence.map(function text(part) { return part.value ?? part.children?.map(text).join('') ?? ''; }).join(''));
- tree.children[index + 1] = html(`${image(card, alt, ' width="100%"')} `);
+ const buttons = links.filter(({button}) => exists(button))
+ .map(({url, button, alt: label}) => `${image(button, label, ' height="48"')} `);
+ tree.children[index + 1] = html(`${image(card, alt, ' width="100%"')} `
+ + (buttons.length ? `\n${buttons.join(' ')}
` : ''));
}
diff --git a/Website/scripts/github-readme.test.mjs b/Website/scripts/github-readme.test.mjs
index 242a95c6..5d8e7c19 100644
--- a/Website/scripts/github-readme.test.mjs
+++ b/Website/scripts/github-readme.test.mjs
@@ -95,14 +95,24 @@ test('the help section becomes the call to action, without the licence line', ()
+ 'Open an issue · Star on GitHub
\n');
});
-test('the donation sentence gives way to the card image, the sentence its alt text', () => {
+test('the donation sentence gives way to the card image and a button per place, the sentence the card alt text', () => {
+ const kofi = 'https://ko-fi.com/owner';
const store = 'https://assetstore.unity.com/packages/package/1';
- const section = `## Support\n\nSupport it on the [Asset Store](${store}).\n`;
- assert.equal(layout(section, ['Website/docs/Images/support-card.svg']), '## Support\n\n'
- + ` \n`);
+ const images = ['support-card.svg', 'support-kofi.svg', 'support-store.svg'].map((name) => `Website/docs/Images/${name}`);
+ const section = `## Support\n\nSupport it on [Ko-fi](${kofi}) or the [Asset Store](${store}).\n`;
+ assert.equal(layout(section, images), '## Support\n\n'
+ + ` \n`
+ + ` `
+ + `
\n`);
assert.equal(layout(section), section, 'without the card image the section stays as it is');
});
+test('the donation card links the Asset Store without a Ko-fi link, and drops a button without its image', () => {
+ const store = 'https://assetstore.unity.com/packages/package/1';
+ assert.equal(layout(`## Support\n\nSupport it on the [Asset Store](${store}).\n`, ['Website/docs/Images/support-card.svg']), '## Support\n\n'
+ + ` \n`);
+});
+
test('images and the banner stay as they are, without a light variant', () => {
const banner = '\n \n \n ';
assert.match(layout(`${banner}\n\n`, ['a-light.png']), / \n<\/picture>\n\n!\[Badge\]\(badge.svg\)/);
diff --git a/Website/scripts/intro-banner.test.mjs b/Website/scripts/intro-banner.test.mjs
index 1354b556..6a00011a 100644
--- a/Website/scripts/intro-banner.test.mjs
+++ b/Website/scripts/intro-banner.test.mjs
@@ -50,11 +50,12 @@ for (const [language, file] of Object.entries(introduction)) {
assert.match(attribute(support, 'repo'), /^https:\/\/github\.com\/[^/]+\/[^/]+\/?$/);
});
- test(`${language} introduction: the donation section becomes a card with a button to the Asset Store`, () => {
+ test(`${language} introduction: the donation section becomes a card with buttons to Ko-fi and the Asset Store`, () => {
const [donate, ...more] = find(tree, element('DonatePanel'));
assert.equal(more.length, 0);
- assert.match(attribute(donate, 'href'), /^https:\/\/assetstore\.unity\.com\//);
- assert.equal(find(donate, node => node.type === 'link').length, 0, 'the button carries the link');
+ assert.match(attribute(donate, 'kofi'), /^https:\/\/ko-fi\.com\//);
+ assert.match(attribute(donate, 'store'), /^https:\/\/assetstore\.unity\.com\//);
+ assert.equal(find(donate, node => node.type === 'link').length, 0, 'the buttons carry the links');
});
test(`${language} introduction: absolute links to the site become site links`, () => {
diff --git a/Website/src/components/DonatePanel/index.js b/Website/src/components/DonatePanel/index.js
index 39a2724c..9e1300d3 100644
--- a/Website/src/components/DonatePanel/index.js
+++ b/Website/src/components/DonatePanel/index.js
@@ -1,16 +1,20 @@
import React from 'react';
+import clsx from 'clsx';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import styles from './styles.module.css';
const TEXT = {
- en: {title: 'Enjoying Aspid.FastTools?', action: 'Support on the Asset Store'},
- ru: {title: 'Нравится Aspid.FastTools?', action: 'Поддержать в Asset Store'},
+ en: {title: 'Enjoying Aspid.FastTools?', kofi: 'Support on Ko-fi', store: 'Asset Store'},
+ ru: {title: 'Нравится Aspid.FastTools?', kofi: 'Поддержать на Ko-fi', store: 'Asset Store'},
};
const HEART = 'M12 21s-7.5-4.6-9.6-9.4C1 8.4 2.9 4.5 6.6 4.5c2.2 0 3.7 1.2 5.4 3.2 1.7-2 3.2-3.2 5.4-3.2 3.7 0 5.6 3.9 4.2 7.1C19.5 16.4 12 21 12 21Z';
-/** The introduction's donation card: a beating heart, the README's sentence and a button to the Asset Store. */
-export default function DonatePanel({href, children}) {
+/**
+ * The introduction's donation card: a beating heart, the README's sentence, a filled button to Ko-fi and a quieter
+ * one to the Asset Store.
+ */
+export default function DonatePanel({kofi, store, children}) {
const {i18n} = useDocusaurusContext();
const text = TEXT[i18n.currentLocale] ?? TEXT.en;
return (
@@ -22,10 +26,19 @@ export default function DonatePanel({href, children}) {
{text.title}
{children}
-
-
- {text.action}
-
+
);
}
diff --git a/Website/src/components/DonatePanel/styles.module.css b/Website/src/components/DonatePanel/styles.module.css
index eee5027a..93cd6e22 100644
--- a/Website/src/components/DonatePanel/styles.module.css
+++ b/Website/src/components/DonatePanel/styles.module.css
@@ -1,7 +1,7 @@
/*
* The donation card closes the introduction, after the support panel. Unlike the quiet panels above it, it carries
* the brand green: a green wash with a glowing gradient frame, a heart that beats every few seconds and a filled
- * button like the support panel's primary action, only larger.
+ * button to Ko-fi like the support panel's primary action, only larger, with an outlined Asset Store button under it.
*/
.donate {
@@ -50,6 +50,7 @@
display: inline-flex;
flex: none;
align-items: center;
+ justify-content: center;
gap: 10px;
padding: 13px 22px;
color: var(--venom-accent-fill-ink);
@@ -68,6 +69,16 @@
filter: brightness(1.06);
box-shadow: 0 12px 26px -10px var(--donate-green);
}
+.actions { display: flex; flex: none; flex-direction: column; gap: 10px; }
+/* The Asset Store button: the same size, outlined instead of filled, so Ko-fi stays the main action. */
+:global(.markdown) a.action.secondary:not(:global(.card)):not(:global(.pagination-nav__link)):not([class*='card_']):not(:global(.table-of-contents__link)) {
+ color: var(--venom-fg-strong);
+ background: transparent;
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--donate-green) 55%, transparent);
+}
+:global(.markdown) a.action.secondary:not(:global(.card)):not(:global(.pagination-nav__link)):not([class*='card_']):not(:global(.table-of-contents__link)):hover {
+ box-shadow: inset 0 0 0 1px var(--donate-green);
+}
.icon { flex: none; width: 17px; height: 17px; fill: currentColor; }
:global(.markdown) a.action:hover .icon { animation: beat 1.2s ease-in-out infinite; }
diff --git a/Website/src/remark/introBanner.js b/Website/src/remark/introBanner.js
index 660f803a..90705caf 100644
--- a/Website/src/remark/introBanner.js
+++ b/Website/src/remark/introBanner.js
@@ -234,19 +234,22 @@ export default function remarkIntroBanner({baseUrl, siteUrl}) {
{type: 'mdxJsxAttribute', name: 'repo', value: repo},
]});
}
- // The donation section — one sentence linking the Asset Store — becomes a card with a button to it; the link in
- // the sentence turns into plain text, since the button carries it.
- const isStore = (url) => /^https:\/\/assetstore\.unity\.com\//.test(url);
+ // The donation section — one sentence linking Ko-fi and the Asset Store — becomes a card with a button to each;
+ // the links in the sentence turn into plain text, since the buttons carry them.
+ const donation = {kofi: (url) => /^https:\/\/ko-fi\.com\//.test(url), store: (url) => /^https:\/\/assetstore\.unity\.com\//.test(url)};
+ const isDonation = (part) => part.type === 'link' && Object.values(donation).some((test) => test(part.url));
const donate = tree.children.findIndex((node, index) => node.type === 'heading' && node.depth === 2
&& tree.children[index + 1]?.type === 'paragraph'
- && tree.children[index + 1].children.some((part) => part.type === 'link' && isStore(part.url))
+ && tree.children[index + 1].children.some(isDonation)
&& (!tree.children[index + 2] || tree.children[index + 2].type === 'heading'));
if (donate !== -1) {
const sentence = tree.children[donate + 1].children;
- const store = sentence.find((part) => part.type === 'link' && isStore(part.url));
tree.children[donate + 1] = {type: 'mdxJsxFlowElement', name: 'DonatePanel',
- attributes: [{type: 'mdxJsxAttribute', name: 'href', value: store.url}],
- children: sentence.flatMap((part) => (part === store ? part.children : [part]))};
+ attributes: Object.entries(donation).flatMap(([name, test]) => {
+ const link = sentence.find((part) => part.type === 'link' && test(part.url));
+ return link ? [{type: 'mdxJsxAttribute', name, value: link.url}] : [];
+ }),
+ children: sentence.flatMap((part) => (isDonation(part) ? part.children : [part]))};
}
// Keep absolute site links on GitHub, and native local links on the site.
function visit(node) {