downgrade: chose the path of ads

This commit is contained in:
Kingkor Roy Tirtho 2024-12-13 00:17:19 +06:00
parent b32ec667a9
commit 12f3ec1776
18 changed files with 356 additions and 83 deletions

View File

@ -50,6 +50,7 @@
"highlight.js": "11.9.0",
"lucide-svelte": "^0.323.0",
"mdsvex-relative-images": "^1.0.3",
"rehype-auto-ads": "^1.2.0",
"rehype-autolink-headings": "^7.1.0",
"rehype-slug": "^6.0.0",
"remark-container": "^0.1.2",

View File

@ -32,6 +32,9 @@ importers:
mdsvex-relative-images:
specifier: ^1.0.3
version: 1.0.3
rehype-auto-ads:
specifier: ^1.2.0
version: 1.2.0
rehype-autolink-headings:
specifier: ^7.1.0
version: 7.1.0
@ -783,6 +786,9 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
comma-separated-tokens@2.0.3:
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
commander@10.0.1:
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
engines: {node: '>=14'}
@ -873,6 +879,10 @@ packages:
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
es6-promise@3.3.1:
resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==}
@ -1069,15 +1079,27 @@ packages:
resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==}
engines: {node: '>= 0.4'}
hast-util-from-html@2.0.3:
resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==}
hast-util-from-parse5@8.0.2:
resolution: {integrity: sha512-SfMzfdAi/zAoZ1KkFEyyeXBn7u/ShQrfd675ZEE9M3qj+PMFX05xubzRyF76CCSJu8au9jgVxDV1+okFvgZU4A==}
hast-util-heading-rank@3.0.0:
resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==}
hast-util-is-element@3.0.0:
resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}
hast-util-parse-selector@4.0.0:
resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}
hast-util-to-string@3.0.0:
resolution: {integrity: sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==}
hastscript@9.0.0:
resolution: {integrity: sha512-jzaLBGavEDKHrc5EfFImKN7nZKKBdSLIdGvCwDZ9TfzbF2ffXiov8CKE445L2Z1Ek2t/m4SKQ2j6Ipv7NyUolw==}
highlight.js@11.9.0:
resolution: {integrity: sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==}
engines: {node: '>=12.0.0'}
@ -1467,6 +1489,9 @@ packages:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
parse5@7.2.1:
resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==}
path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
@ -1609,6 +1634,9 @@ packages:
resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==}
engines: {node: '>=6'}
property-information@6.5.0:
resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==}
punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
@ -1634,6 +1662,9 @@ packages:
resolution: {integrity: sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==}
engines: {node: '>=8'}
rehype-auto-ads@1.2.0:
resolution: {integrity: sha512-w0ysjJQginhKai13wcUF/4t1fu3UvPsVt4Y3htGGGs6ojA+J5Nz01I1NOqwrOhgSoT5Bfv7Mihww6tmtV108+g==}
rehype-autolink-headings@7.1.0:
resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==}
@ -1960,6 +1991,9 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
vfile-location@5.0.3:
resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==}
vfile-message@2.0.4:
resolution: {integrity: sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==}
@ -2016,6 +2050,9 @@ packages:
vite:
optional: true
web-namespaces@2.0.1:
resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}
@ -2660,6 +2697,8 @@ snapshots:
color-name@1.1.4: {}
comma-separated-tokens@2.0.3: {}
commander@10.0.1: {}
commander@4.1.1: {}
@ -2725,6 +2764,8 @@ snapshots:
emoji-regex@9.2.2: {}
entities@4.5.0: {}
es6-promise@3.3.1: {}
esbuild@0.19.12:
@ -2982,6 +3023,26 @@ snapshots:
dependencies:
function-bind: 1.1.2
hast-util-from-html@2.0.3:
dependencies:
'@types/hast': 3.0.4
devlop: 1.1.0
hast-util-from-parse5: 8.0.2
parse5: 7.2.1
vfile: 6.0.1
vfile-message: 4.0.2
hast-util-from-parse5@8.0.2:
dependencies:
'@types/hast': 3.0.4
'@types/unist': 3.0.2
devlop: 1.1.0
hastscript: 9.0.0
property-information: 6.5.0
vfile: 6.0.1
vfile-location: 5.0.3
web-namespaces: 2.0.1
hast-util-heading-rank@3.0.0:
dependencies:
'@types/hast': 3.0.4
@ -2990,10 +3051,22 @@ snapshots:
dependencies:
'@types/hast': 3.0.4
hast-util-parse-selector@4.0.0:
dependencies:
'@types/hast': 3.0.4
hast-util-to-string@3.0.0:
dependencies:
'@types/hast': 3.0.4
hastscript@9.0.0:
dependencies:
'@types/hast': 3.0.4
comma-separated-tokens: 2.0.3
hast-util-parse-selector: 4.0.0
property-information: 6.5.0
space-separated-tokens: 2.0.2
highlight.js@11.9.0: {}
ignore@5.3.1: {}
@ -3510,6 +3583,10 @@ snapshots:
dependencies:
callsites: 3.1.0
parse5@7.2.1:
dependencies:
entities: 4.5.0
path-exists@4.0.0: {}
path-is-absolute@1.0.1: {}
@ -3617,6 +3694,8 @@ snapshots:
prismjs@1.29.0: {}
property-information@6.5.0: {}
punycode@2.3.1: {}
purgecss@6.0.0-alpha.0:
@ -3640,6 +3719,15 @@ snapshots:
regexparam@3.0.0: {}
rehype-auto-ads@1.2.0:
dependencies:
'@types/hast': 3.0.4
hast-util-from-html: 2.0.3
hast-util-is-element: 3.0.0
unified: 11.0.4
unist-util-visit-parents: 6.0.1
vfile: 6.0.1
rehype-autolink-headings@7.1.0:
dependencies:
'@types/hast': 3.0.4
@ -4072,6 +4160,11 @@ snapshots:
util-deprecate@1.0.2: {}
vfile-location@5.0.3:
dependencies:
'@types/unist': 3.0.2
vfile: 6.0.1
vfile-message@2.0.4:
dependencies:
'@types/unist': 2.0.10
@ -4119,6 +4212,8 @@ snapshots:
optionalDependencies:
vite: 5.1.0(@types/node@20.11.16)
web-namespaces@2.0.1: {}
which@2.0.2:
dependencies:
isexe: 2.0.0

View File

@ -3,6 +3,7 @@ title: Spotube Basics
author: Kingkor Roy Tirtho
date: 2024-02-10
published: true
cover_img: /images/spotube-basics/cover.jpg
---
Spotube is an open-source Spotify client that allows users to stream music from Spotify. To use Spotube, you need to sign in with your Spotify account. Here's a step-by-step guide on how to sign in to Spotube.

View File

@ -17,6 +17,10 @@ declare namespace App {
}
}
declare module '@fortawesome/pro-solid-svg-icons/index.es' {
export * from '@fortawesome/pro-solid-svg-icons';
declare namespace globalThis {
declare var adsbygoogle: any[];
}
declare module "@fortawesome/pro-solid-svg-icons/index.es" {
export * from "@fortawesome/pro-solid-svg-icons";
}

View File

@ -13,6 +13,9 @@
<link rel="apple-touch-icon" href="%sveltekit.assets%/apple-touch-icon.png" />
<!-- Android Chrome -->
<link rel="manifest" href="%sveltekit.assets%/manifest.json" />
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-6419300932495863"
crossorigin="anonymous"></script>
%sveltekit.head%
</head>

View File

@ -0,0 +1,32 @@
<script lang="ts">
import { onMount } from 'svelte';
export let adSlot: number;
export let adFormat: 'auto' | 'fluid';
// biome-ignore lint/style/useConst: This is just props
export let fullWidthResponsive = true;
// biome-ignore lint/style/useConst: This is just props
export let style = 'display:block';
// biome-ignore lint/style/useConst: This is just props
export let adLayout: 'in-article' | 'in-feed' | 'in-page' | undefined = undefined;
// biome-ignore lint/style/useConst: This is just props
export let adLayoutKey: string | undefined = undefined;
const AD_CLIENT = 'ca-pub-6419300932495863';
onMount(() => {
// biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
(window.adsbygoogle = window.adsbygoogle || []).push({});
});
</script>
<ins
class="adsbygoogle"
{style}
data-ad-layout={adLayout}
data-ad-client={AD_CLIENT}
data-ad-slot={adSlot}
data-ad-format={adFormat}
data-full-width-responsive={fullWidthResponsive}
data-ad-layout-key={adLayoutKey}
></ins>

View File

@ -17,10 +17,8 @@
</script>
<div class="inline-flex gap-2">
{#if label}
<label class="ps-4">{label}</label>
{/if}
<SlideToggle
label={label}
active="bg-primary-backdrop-token"
size="sm"
name="dark-mode"

View File

@ -6,56 +6,99 @@ import {
faOpensuse,
faUbuntu,
faWindows,
faRedhat
} from '@fortawesome/free-brands-svg-icons';
import { type IconDefinition } from '@fortawesome/free-brands-svg-icons/index';
import { Home, Newspaper, Download } from 'lucide-svelte';
faRedhat,
} from "@fortawesome/free-brands-svg-icons";
import type { IconDefinition } from "@fortawesome/free-brands-svg-icons/index";
import { Home, Newspaper, Download } from "lucide-svelte";
export const routes: Record<string, [string, any]> = {
'/': ['Home', Home],
'/blog': ['Blog', Newspaper],
'/downloads': ['Downloads', Download],
'/about': ['About', null]
"/": ["Home", Home],
"/blog": ["Blog", Newspaper],
"/downloads": ["Downloads", Download],
"/about": ["About", null],
};
const releasesUrl = 'https://github.com/KRTirtho/Spotube/releases/latest/download';
const releasesUrl =
"https://github.com/KRTirtho/Spotube/releases/latest/download";
export const downloadLinks: Record<string, [string, IconDefinition[]]> = {
'Android Apk': [`${releasesUrl}/Spotube-android-all-arch.apk`, [faAndroid]],
'Windows Executable': [`${releasesUrl}/Spotube-windows-x86_64-setup.exe`, [faWindows]],
'macOS Dmg': [`${releasesUrl}/Spotube-macos-universal.dmg`, [faApple]],
'Ubuntu, Debian': [`${releasesUrl}/Spotube-linux-x86_64.deb`, [faUbuntu, faDebian]],
'Fedora, Redhat, Opensuse': [
`${releasesUrl}/Spotube-linux-x86_64.rpm`,
[faFedora, faRedhat, faOpensuse]
"Android Apk": [`${releasesUrl}/Spotube-android-all-arch.apk`, [faAndroid]],
"Windows Executable": [
`${releasesUrl}/Spotube-windows-x86_64-setup.exe`,
[faWindows],
],
'iPhone Ipa': [`${releasesUrl}/Spotube-iOS.ipa`, [faApple]]
};
export const extendedDownloadLinks: Record<string, [string, IconDefinition[], string]> = {
Android: [`${releasesUrl}/Spotube-android-all-arch.apk`, [faAndroid], 'apk'],
Windows: [`${releasesUrl}/Spotube-windows-x86_64-setup.exe`, [faWindows], 'exe'],
macOS: [`${releasesUrl}/Spotube-macos-universal.dmg`, [faApple], 'dmg'],
'Ubuntu, Debian': [`${releasesUrl}/Spotube-linux-x86_64.deb`, [faUbuntu, faDebian], 'deb'],
'Fedora, Redhat, Opensuse': [
"macOS Dmg": [`${releasesUrl}/Spotube-macos-universal.dmg`, [faApple]],
"Ubuntu, Debian": [
`${releasesUrl}/Spotube-linux-x86_64.deb`,
[faUbuntu, faDebian],
],
"Fedora, Redhat, Opensuse": [
`${releasesUrl}/Spotube-linux-x86_64.rpm`,
[faFedora, faRedhat, faOpensuse],
'rpm'
],
iPhone: [`${releasesUrl}/Spotube-iOS.ipa`, [faApple], 'ipa']
"iPhone Ipa": [`${releasesUrl}/Spotube-iOS.ipa`, [faApple]],
};
const nightlyReleaseUrl = 'https://github.com/KRTirtho/Spotube/releases/download/nightly';
export const extendedDownloadLinks: Record<
string,
[string, IconDefinition[], string]
> = {
Android: [`${releasesUrl}/Spotube-android-all-arch.apk`, [faAndroid], "apk"],
Windows: [
`${releasesUrl}/Spotube-windows-x86_64-setup.exe`,
[faWindows],
"exe",
],
macOS: [`${releasesUrl}/Spotube-macos-universal.dmg`, [faApple], "dmg"],
"Ubuntu, Debian": [
`${releasesUrl}/Spotube-linux-x86_64.deb`,
[faUbuntu, faDebian],
"deb",
],
"Fedora, Redhat, Opensuse": [
`${releasesUrl}/Spotube-linux-x86_64.rpm`,
[faFedora, faRedhat, faOpensuse],
"rpm",
],
iPhone: [`${releasesUrl}/Spotube-iOS.ipa`, [faApple], "ipa"],
};
export const extendedNightlyDownloadLinks: Record<string, [string, IconDefinition[], string]> = {
Android: [`${nightlyReleaseUrl}/Spotube-android-all-arch.apk`, [faAndroid], 'apk'],
Windows: [`${nightlyReleaseUrl}/Spotube-windows-x86_64-setup.exe`, [faWindows], 'exe'],
macOS: [`${nightlyReleaseUrl}/Spotube-macos-universal.dmg`, [faApple], 'dmg'],
'Ubuntu, Debian': [`${nightlyReleaseUrl}/Spotube-linux-x86_64.deb`, [faUbuntu, faDebian], 'deb'],
'Fedora, Redhat, Opensuse': [
const nightlyReleaseUrl =
"https://github.com/KRTirtho/Spotube/releases/download/nightly";
export const extendedNightlyDownloadLinks: Record<
string,
[string, IconDefinition[], string]
> = {
Android: [
`${nightlyReleaseUrl}/Spotube-android-all-arch.apk`,
[faAndroid],
"apk",
],
Windows: [
`${nightlyReleaseUrl}/Spotube-windows-x86_64-setup.exe`,
[faWindows],
"exe",
],
macOS: [`${nightlyReleaseUrl}/Spotube-macos-universal.dmg`, [faApple], "dmg"],
"Ubuntu, Debian": [
`${nightlyReleaseUrl}/Spotube-linux-x86_64.deb`,
[faUbuntu, faDebian],
"deb",
],
"Fedora, Redhat, Opensuse": [
`${nightlyReleaseUrl}/Spotube-linux-x86_64.rpm`,
[faFedora, faRedhat, faOpensuse],
'rpm'
"rpm",
],
iPhone: [`${nightlyReleaseUrl}/Spotube-iOS.ipa`, [faApple], 'ipa']
iPhone: [`${nightlyReleaseUrl}/Spotube-iOS.ipa`, [faApple], "ipa"],
};
export const ADS_SLOTS = Object.freeze({
rootPageDisplay: 5979549631,
blogPageInFeed: 3386010031,
downloadPageDisplay: 9521642154,
packagePageArticle: 9119323068,
// This is being used for rehype-auto-ads in svelte.config.js
blogArticlePageArticle: 6788673194,
});

View File

@ -4,6 +4,7 @@ export interface Post {
tags: string[];
published: boolean;
author: string;
cover_img: string | null;
readingTime: {
text: string;
minutes: number;
@ -21,21 +22,23 @@ export interface Post {
export const getPosts = async () => {
// Fetch posts from local Markdown files
const posts: Post[] = await Promise.all(
Object.entries(import.meta.glob('../../posts/**/*.md')).map(async ([path, resolver]) => {
const resolved = (await resolver()) as { metadata: Post };
const { metadata } = resolved;
const slug = path.split('/').pop()?.slice(0, -3) ?? '';
return { ...metadata, slug };
})
);
Object.entries(import.meta.glob("../../posts/**/*.md")).map(
async ([path, resolver]) => {
const resolved = (await resolver()) as { metadata: Post };
const { metadata } = resolved;
const slug = path.split("/").pop()?.slice(0, -3) ?? "";
return { ...metadata, slug };
},
),
).then((posts) => posts.filter((post) => post.published));
let sortedPosts = posts.sort((a, b) => +new Date(b.date) - +new Date(a.date));
sortedPosts = sortedPosts.map((post) => ({
...post
...post,
}));
return {
posts: sortedPosts
posts: sortedPosts,
};
};

View File

@ -10,6 +10,8 @@
import { Download, Heart } from 'lucide-svelte';
import type { PageData } from './$types';
import { Avatar } from '@skeletonlabs/skeleton';
import Ads from '$lib/components/ads/ads.svelte';
import { ADS_SLOTS } from '$lib';
export let data: PageData;
@ -75,6 +77,8 @@
</a>
</div>
<Ads adSlot={ADS_SLOTS.rootPageDisplay} adFormat="auto" />
<br /><br />
<h2 class="h2">
@ -111,4 +115,5 @@
</a>
{/each}
</div>
<Ads adSlot={ADS_SLOTS.rootPageDisplay} adFormat="auto" />
</section>

View File

@ -1,4 +1,7 @@
<script lang="ts">
import { ADS_SLOTS } from '$lib';
import Ads from '$lib/components/ads/ads.svelte';
import type { Post } from '$lib/posts';
import type { PageData } from './$types';
export let data: PageData;
@ -6,27 +9,67 @@
const formatter = Intl.DateTimeFormat('en-US', {
dateStyle: 'medium'
});
// insert a special Post as ad type in the posts array
const adAddedPosts: Post[] = [];
for (const post of data.posts) {
adAddedPosts.push(post);
const index = adAddedPosts.indexOf(post);
if (index % 3 === 0) {
adAddedPosts.push({
title: 'Ad',
author: 'Ad',
cover_img: 'ad.jpg',
date: new Date().toISOString(),
path: '/ad',
preview: 'Ad',
preview_html: 'Ad',
previewHtml: 'Ad',
published: true,
reading_time_text: 'Ad',
readingTime: { minutes: 1, words: 1, text: 'Ad', time: 1 },
slug: 'ad',
tags: ['Ad']
});
}
}
</script>
<section class="p-4 md:p-16 flex flex-col gap-4">
<h2 class="h2">Blog Posts</h2>
<br />
<article class="grid sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4">
{#each data.posts as post}
<a
href={`/blog/${post.slug}`}
class="card hover:brightness-95 active:bg-secondary-hover-token active:scale-95 transition-all variant-ghost-secondary p-4"
>
<h4 class="h4">{post.title}</h4>
<p>By {post.author}</p>
<br />
<p class="text-end">
Published on
<span class="font-medium underline decoration-dotted">
{formatter.format(new Date(post.date))}
</span>
</p>
</a>
<article class="grid sm:grid-cols-2 md:grid-cols-3 2xl:grid-cols-4">
{#each adAddedPosts as post}
{#if post.slug === 'ad'}
<Ads
adSlot={ADS_SLOTS.blogPageInFeed}
adFormat="fluid"
adLayoutKey="-6l+eh+17-40+59"
fullWidthResponsive={false}
/>
{:else}
<a
href={`/blog/${post.slug}`}
class="card hover:brightness-95 active:bg-secondary-hover-token active:scale-95 transition-all variant-ghost-secondary p-4"
>
<img
src={`/posts/${post.cover_img}`}
alt={post.title}
class="rounded h-56 w-full object-cover"
/>
<h4 class="h4">{post.title}</h4>
<p>By {post.author}</p>
<br />
<p class="text-end">
Published on
<span class="font-medium underline decoration-dotted">
{formatter.format(new Date(post.date))}
</span>
</p>
</a>
{/if}
{/each}
</article>
</section>

View File

@ -1,11 +1,10 @@
import type { Post } from '$lib/posts.js';
import type { Post } from "$lib/posts.js";
export const load = async ({ fetch }) => {
const res = await fetch(`api/posts`);
const res = await fetch("api/posts");
if (res.ok) {
const posts: Post[] = await res.json();
return { posts };
} else {
return { posts: [] };
}
return { posts: [] };
};

View File

@ -3,9 +3,9 @@
import type { PageData } from './$types';
export let data: PageData;
let {
const {
Content,
meta: { date, title, readingTime }
meta: { date, title, readingTime, cover_img }
} = data as Required<PageData>;
</script>
@ -14,13 +14,19 @@
</svelte:head>
<article class="p-4 md:p-16 flex flex-grow flex-col">
<h1 class="h1">{title}</h1>
<section
class={cover_img
? 'bg-black/30 h-56 md:h-80 xl:h-96 bg-cover bg-center flex flex-col justify-end p-4 pb-0 md:p-8 md:pb-0 rounded-lg'
: null}
style={cover_img ? `background-image: url(/posts/${cover_img});` : ''}
>
<h1 class={`h1 ${cover_img ? 'text-white' : ''}`}>{title}</h1>
<br />
<p class={cover_img ? 'text-gray-400' : ''}>{new Date(date).toDateString()}</p>
<p class={`mb-16 ${cover_img ? 'text-gray-400' : ''}`}>{readingTime?.text ?? ''}</p>
</section>
<br />
<div class="">
<p>{new Date(date).toDateString()}</p>
<p class="mb-16">{readingTime?.text ?? ''}</p>
<Layout>
<svelte:component this={Content} />
</Layout>
</div>
<Layout>
<svelte:component this={Content} />
</Layout>
</article>

View File

@ -1,8 +1,9 @@
<script lang="ts">
import { extendedDownloadLinks } from '$lib';
import { ADS_SLOTS, extendedDownloadLinks } from '$lib';
import { Download } from 'lucide-svelte';
import { History, Sparkles, Package } from 'lucide-svelte';
import DownloadItems from '$lib/components/downloads/download-items.svelte';
import Ads from '$lib/components/ads/ads.svelte';
const otherDownloads: [string, string, any][] = [
['/downloads/packages', 'CLI Packages Managers', Package],
@ -11,7 +12,7 @@
];
</script>
<section class="p-4 md:p-16">
<section class="p-4 md:p-16 md:pb-4">
<h2 class="h2 flex items-center gap-4">
Download
<Download class="inline" size={30} />
@ -22,7 +23,7 @@
<DownloadItems links={extendedDownloadLinks} />
<br /><br /><br />
<Ads adSlot={ADS_SLOTS.downloadPageDisplay} adFormat="auto" />
<h2 class="h2">Other Downloads</h2>
<br /><br />
@ -36,4 +37,5 @@
</a>
{/each}
</div>
<Ads adSlot={ADS_SLOTS.downloadPageDisplay} adFormat="auto" />
</section>

View File

@ -6,6 +6,8 @@ author: Kingkor Roy Tirtho
<script lang="ts">
import { faLinux, faWindows, faApple } from '@fortawesome/free-brands-svg-icons';
import Fa from 'svelte-fa';
import Ads from '$lib/components/ads/ads.svelte';
import { ADS_SLOTS } from '$lib';
</script>
<div class="p-4 md:ps-24">
@ -40,6 +42,14 @@ $ pamac install spotube-bin
$ paru -Sy spotube-bin
```
<Ads
style="display:block; text-align:center;"
adSlot={ADS_SLOTS.packagePageArticle}
adLayout="in-article"
adFormat="fluid"
fullWidthResponsive={false}
/>
## <Fa class="inline" icon={faApple} /> MacOS
### Homebrew🍻
@ -51,6 +61,14 @@ $ brew tap krtirtho/apps
$ brew install --cask spotube
```
<Ads
style="display:block; text-align:center;"
adSlot={ADS_SLOTS.packagePageArticle}
adLayout="in-article"
adFormat="fluid"
fullWidthResponsive={false}
/>
## <Fa class="inline" icon={faWindows} color="#00A2F0" /> Windows
### Chocolatey🍫

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

View File

@ -7,6 +7,7 @@ import slugPlugin from 'rehype-slug';
import autolinkHeadings from 'rehype-autolink-headings';
import relativeImages from 'mdsvex-relative-images';
import remarkGfm from 'remark-gfm';
import rehypeAutoAds from 'rehype-auto-ads';
/** @type {import('@sveltejs/kit').Config} */
const config = {
@ -38,6 +39,25 @@ const config = {
{
behavior: 'wrap'
}
],
[
rehypeAutoAds,
{
adCode: `
<ins class="adsbygoogle"
style="display:block; text-align:center;"
data-ad-layout="in-article"
data-ad-format="fluid"
data-ad-client="ca-pub-6419300932495863"
data-ad-slot="6788673194"
></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
`,
paragraphInterval: 2,
maxAds: 5,
}
]
]
})