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 -Aspid.FastTools is developed in spare time. If it helps you, support its development on the Unity Asset Store. +Aspid.FastTools is developed in spare time. If it helps you, support its development on Ko-fi or the Unity Asset Store. +

Support on Ko-fi  Unity Asset Store

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' - + `Support it on the Asset Store.\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' + + `Support it on Ko-fi or the Asset Store.\n` + + `

Support on Ko-fi  ` + + `Unity Asset Store

\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' + + `Support it on the Asset Store.\n`); +}); + test('images and the banner stay as they are, without a light variant', () => { const banner = '\n \n Banner\n'; assert.match(layout(`${banner}\n\n![Badge](badge.svg)`, ['a-light.png']), /Banner\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} - +
+ {kofi && ( + + + {text.kofi} + + )} + {store && ( + + {text.store} + + )} +
); } 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) {