3 Commits 2b517d0e6a ... 9b0afab9cf

Author SHA1 Message Date
  codeskraps 9b0afab9cf Update all links to use the production URL instead of localhost across various HTML, XML, and sitemap files. Enhance styling for header sections in multiple pages by removing inline scripts and improving layout consistency. 1 week ago
  codeskraps 92bda1cf85 Enhance styling for code blocks in posts and layouts, including border and padding adjustments. Update all links to use the production URL instead of localhost for consistency across the site. 1 week ago
  codeskraps 272a938b57 Implement code copy functionality across various posts and layouts, updating syntax highlighting to a new shortcode. Adjust links to use localhost for local development and enhance styling for code blocks. 1 week ago

+ 12 - 12
content/posts/2024/git_ssh_command.md

@@ -16,9 +16,9 @@ Git provides a handy way to set configuration options for a single command using
 
 
 Here's the syntax:
 Here's the syntax:
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 git -c core.sshCommand="ssh -i /path/to/private_key_file" <git command>
 git -c core.sshCommand="ssh -i /path/to/private_key_file" <git command>
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 ## Examples
 ## Examples
 
 
@@ -26,26 +26,26 @@ git -c core.sshCommand="ssh -i /path/to/private_key_file" <git command>
 
 
 To clone a repository using a specific SSH key:
 To clone a repository using a specific SSH key:
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 git -c core.sshCommand="ssh -i /path/to/private_key_file" clone git@github.com:username/repo.git
 git -c core.sshCommand="ssh -i /path/to/private_key_file" clone git@github.com:username/repo.git
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 ### Adding a Submodule
 ### Adding a Submodule
 
 
 Similarly, when adding a submodule:
 Similarly, when adding a submodule:
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 git -c core.sshCommand="ssh -i /path/to/private_key_file" submodule add git@github.com:username/submodule.git
 git -c core.sshCommand="ssh -i /path/to/private_key_file" submodule add git@github.com:username/submodule.git
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 ## Making SSH Keys Available
 ## Making SSH Keys Available
 
 
 Before using SSH keys with Git, it's important to check which keys are already available on your system:
 Before using SSH keys with Git, it's important to check which keys are already available on your system:
 
 
 1. **Check Available Keys**: List the contents of your SSH directory:
 1. **Check Available Keys**: List the contents of your SSH directory:
-   {{<highlight bash>}}
+   {{<codewithcopy bash>}}
    ls -al ~/.ssh
    ls -al ~/.ssh
-   {{</highlight>}}
+   {{</codewithcopy>}}
    This command will show you all files in your SSH directory, including your key files (typically with extensions like .pub for public keys).
    This command will show you all files in your SSH directory, including your key files (typically with extensions like .pub for public keys).
 
 
 2. **Common Key Names**: Look for files like:
 2. **Common Key Names**: Look for files like:
@@ -54,10 +54,10 @@ Before using SSH keys with Git, it's important to check which keys are already a
    - id_ecdsa, id_ecdsa.pub
    - id_ecdsa, id_ecdsa.pub
 
 
 3. **Add to SSH Agent**: If you find the key you want to use, ensure it's added to your SSH agent:
 3. **Add to SSH Agent**: If you find the key you want to use, ensure it's added to your SSH agent:
-   {{<highlight bash>}}
+   {{<codewithcopy bash>}}
    eval "$(ssh-agent -s)"
    eval "$(ssh-agent -s)"
    ssh-add ~/.ssh/your_private_key_file
    ssh-add ~/.ssh/your_private_key_file
-   {{</highlight>}}
+   {{</codewithcopy>}}
 
 
 4. **Verify Key in Git Host**: Make sure the corresponding public key (the .pub file) is added to your Git host (e.g., GitHub, GitLab) in the SSH keys section of your account settings.
 4. **Verify Key in Git Host**: Make sure the corresponding public key (the .pub file) is added to your Git host (e.g., GitHub, GitLab) in the SSH keys section of your account settings.
 
 
@@ -73,10 +73,10 @@ After cloning a repository using the method described above, you might want to m
 
 
 3. Add the following lines under the `[core]` section (or create it if it doesn't exist):
 3. Add the following lines under the `[core]` section (or create it if it doesn't exist):
 
 
-   {{<highlight ini>}}
+   {{<codewithcopy ini>}}
    [core]
    [core]
        sshCommand = ssh -i /path/to/private_key_file
        sshCommand = ssh -i /path/to/private_key_file
-   {{</highlight>}}
+   {{</codewithcopy>}}
 
 
 4. Save and close the file.
 4. Save and close the file.
 
 

+ 2 - 2
content/posts/2024/gitignore_not_working.md

@@ -24,10 +24,10 @@ Fear not! There's a simple (if somewhat counterintuitive) fix. Here's what you n
 
 
 2. Then, run these two commands:
 2. Then, run these two commands:
 
 
-   {{<highlight bash>}}
+   {{<codewithcopy bash>}}
    git rm -rf --cached .
    git rm -rf --cached .
    git add .
    git add .
-   {{</highlight>}}
+   {{</codewithcopy>}}
 
 
 Let's break down what these commands do:
 Let's break down what these commands do:
 
 

+ 6 - 6
content/posts/2024/mvi_architecture.md

@@ -10,7 +10,7 @@ Model-View-Intent (MVI) is a powerful architectural pattern for building user in
 
 
 First, let's look at the complete helper class:
 First, let's look at the complete helper class:
 
 
-{{< highlight kotlin >}}
+{{<codewithcopy kotlin>}}
 interface StateReceiver<STATE> {
 interface StateReceiver<STATE> {
     suspend fun updateState(transform: suspend (STATE) -> STATE)
     suspend fun updateState(transform: suspend (STATE) -> STATE)
     suspend fun withState(block: suspend (STATE) -> Unit)
     suspend fun withState(block: suspend (STATE) -> Unit)
@@ -81,7 +81,7 @@ class MVIViewModelDelegate<STATE, INTENT, ACTION>(
         throw NotImplementedError()
         throw NotImplementedError()
     }
     }
 }
 }
-{{< /highlight >}}
+{{</codewithcopy>}}
 
 
 ## Understanding the MVI Helper Class
 ## Understanding the MVI Helper Class
 
 
@@ -115,7 +115,7 @@ This class implements the `MVIViewModel` interface, providing a concrete impleme
 
 
 Let's implement a simple counter application using our MVI helper class. Note that we can use either data classes or sealed interfaces for our State, Intent, and Action definitions:
 Let's implement a simple counter application using our MVI helper class. Note that we can use either data classes or sealed interfaces for our State, Intent, and Action definitions:
 
 
-{{< highlight kotlin >}}
+{{<codewithcopy kotlin>}}
 // Define our State, Intent, and Action
 // Define our State, Intent, and Action
 data class CounterState(val count: Int = 0)
 data class CounterState(val count: Int = 0)
 
 
@@ -150,7 +150,7 @@ class CounterViewModel : MVIViewModel<CounterState, CounterIntent, CounterAction
         }
         }
     }
     }
 }
 }
-{{< /highlight >}}
+{{</codewithcopy>}}
 
 
 In this example:
 In this example:
 
 
@@ -163,7 +163,7 @@ In this example:
 
 
 Here's how you might use this ViewModel in an Android Activity or Fragment:
 Here's how you might use this ViewModel in an Android Activity or Fragment:
 
 
-{{< highlight kotlin >}}
+{{<codewithcopy kotlin>}}
 class CounterActivity : AppCompatActivity() {
 class CounterActivity : AppCompatActivity() {
     private val viewModel: CounterViewModel by viewModels()
     private val viewModel: CounterViewModel by viewModels()
 
 
@@ -200,7 +200,7 @@ class CounterActivity : AppCompatActivity() {
         counterTextView.text = state.count.toString()
         counterTextView.text = state.count.toString()
     }
     }
 }
 }
-{{< /highlight >}}
+{{</codewithcopy>}}
 
 
 ## Conclusion
 ## Conclusion
 
 

+ 4 - 4
content/posts/2024/react_vs_kmp.md

@@ -24,7 +24,7 @@ Kotlin Multiplatform, developed by JetBrains, takes a different approach. Introd
 
 
 React Native's use of JavaScript as its primary language is a significant advantage for many developers, especially those with a web development background. JavaScript's popularity and the vast ecosystem of tools and libraries make it an accessible choice for beginners and experienced developers alike.
 React Native's use of JavaScript as its primary language is a significant advantage for many developers, especially those with a web development background. JavaScript's popularity and the vast ecosystem of tools and libraries make it an accessible choice for beginners and experienced developers alike.
 
 
-{{< highlight javascript >}}
+{{<codewithcopy javascript>}}
 import React from 'react';
 import React from 'react';
 import { Text, View } from 'react-native';
 import { Text, View } from 'react-native';
 
 
@@ -37,7 +37,7 @@ const HelloWorldApp = () => {
 }
 }
 
 
 export default HelloWorldApp;
 export default HelloWorldApp;
-{{< /highlight >}}
+{{</codewithcopy>}}
 
 
 This familiarity can lead to faster onboarding and development cycles, particularly for teams already versed in web technologies.
 This familiarity can lead to faster onboarding and development cycles, particularly for teams already versed in web technologies.
 
 
@@ -45,7 +45,7 @@ This familiarity can lead to faster onboarding and development cycles, particula
 
 
 Kotlin Multiplatform, on the other hand, leverages the power and expressiveness of the Kotlin language. While it may have a steeper learning curve for those not familiar with Kotlin, it offers numerous benefits.
 Kotlin Multiplatform, on the other hand, leverages the power and expressiveness of the Kotlin language. While it may have a steeper learning curve for those not familiar with Kotlin, it offers numerous benefits.
 
 
-{{< highlight kotlin >}}
+{{<codewithcopy kotlin>}}
 expect class Platform()
 expect class Platform()
 expect fun Platform.name(): String
 expect fun Platform.name(): String
 
 
@@ -56,7 +56,7 @@ fun greet(): String = hello() + " on " + Platform().name()
 class Greeting {
 class Greeting {
     fun greeting(): String = greet()
     fun greeting(): String = greet()
 }
 }
-{{< /highlight >}}
+{{</codewithcopy>}}
 
 
 These features can lead to more robust, maintainable code, which can be especially beneficial for larger, more complex projects.
 These features can lead to more robust, maintainable code, which can be especially beneficial for larger, more complex projects.
 
 

+ 26 - 26
content/posts/2025/move_home_folder.md

@@ -12,91 +12,91 @@ You can move the `/home` folder on Ubuntu, but you must do it carefully to avoid
 ## **1. Create a Backup (Recommended)**
 ## **1. Create a Backup (Recommended)**
 Before proceeding, create a backup of your home folder in case anything goes wrong.
 Before proceeding, create a backup of your home folder in case anything goes wrong.
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 sudo tar -czvf /home_backup.tar.gz /home
 sudo tar -czvf /home_backup.tar.gz /home
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 ## **2. Create a New Partition or Mount Point (If Needed)**
 ## **2. Create a New Partition or Mount Point (If Needed)**
 If you're moving /home to a different partition or disk, make sure it's properly formatted and mounted.
 If you're moving /home to a different partition or disk, make sure it's properly formatted and mounted.
 
 
 For example, if you want to use a new disk (e.g., `/dev/sdb1`):
 For example, if you want to use a new disk (e.g., `/dev/sdb1`):
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 sudo mkfs.ext4 /dev/sdb1
 sudo mkfs.ext4 /dev/sdb1
 sudo mkdir /mnt/newhome
 sudo mkdir /mnt/newhome
 sudo mount /dev/sdb1 /mnt/newhome
 sudo mount /dev/sdb1 /mnt/newhome
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 ## **3. Copy the Home Folder**
 ## **3. Copy the Home Folder**
 Copy all user data to the new location while preserving permissions:
 Copy all user data to the new location while preserving permissions:
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 sudo rsync -aXS /home/ /mnt/newhome/
 sudo rsync -aXS /home/ /mnt/newhome/
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 ---
 ---
 
 
 ## **4. Update fstab**
 ## **4. Update fstab**
 Edit /etc/fstab to mount the new home directory at boot.
 Edit /etc/fstab to mount the new home directory at boot.
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 sudo nano /etc/fstab
 sudo nano /etc/fstab
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 Add this line at the end (adjust the path accordingly):
 Add this line at the end (adjust the path accordingly):
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 /dev/sdb1  /home  ext4  defaults  0  2
 /dev/sdb1  /home  ext4  defaults  0  2
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 If you prefer using the UUID, first find it:
 If you prefer using the UUID, first find it:
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 sudo blkid
 sudo blkid
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 Then, add this line instead:
 Then, add this line instead:
 
 
-{{<highlight arduino>}}
+{{<codewithcopy arduino>}}
 UUID=your-uuid /home ext4 defaults 0 2
 UUID=your-uuid /home ext4 defaults 0 2
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 ---
 ---
 
 
 ## **5. Unmount Old Home and Mount New One**
 ## **5. Unmount Old Home and Mount New One**
 Switch to a different session (e.g., TTY):
 Switch to a different session (e.g., TTY):
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 Ctrl + Alt + F3
 Ctrl + Alt + F3
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 Log in and stop processes using `/home`:
 Log in and stop processes using `/home`:
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 sudo systemctl stop gdm  # For GNOME (or use sddm/lightdm if applicable)
 sudo systemctl stop gdm  # For GNOME (or use sddm/lightdm if applicable)
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 Unmount and remount:
 Unmount and remount:
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 sudo umount /home
 sudo umount /home
 sudo mount /home
 sudo mount /home
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 ---
 ---
 
 
 ## **6. Verify and Reboot**
 ## **6. Verify and Reboot**
 Check that everything is in place:
 Check that everything is in place:
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 ls /home
 ls /home
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 If everything looks good, reboot:
 If everything looks good, reboot:
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 sudo reboot
 sudo reboot
-{{</highlight>}}
+{{</codewithcopy>}}
 
 
 ---
 ---
 
 
@@ -105,6 +105,6 @@ sudo reboot
 
 
 * If you face permission issues, you might need to reapply ownership:
 * If you face permission issues, you might need to reapply ownership:
 
 
-{{<highlight bash>}}
+{{<codewithcopy bash>}}
 sudo chown -R username:username /home/username
 sudo chown -R username:username /home/username
-{{</highlight>}}
+{{</codewithcopy>}}

+ 3 - 0
layouts/partials/head-additions.html

@@ -0,0 +1,3 @@
+<!-- Code copy functionality -->
+<link rel="stylesheet" href="/css/code-copy.css">
+<script defer src="/js/code-copy.js"></script> 

+ 125 - 0
layouts/shortcodes/codewithcopy.html

@@ -0,0 +1,125 @@
+{{ $lang := .Get 0 }}
+<style>
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    border: 1px solid #5E5E5E;
+    border-radius: 1px;
+    overflow: hidden;
+}
+
+.code-header {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    z-index: 999;
+}
+
+.copy-button {
+    display: inline-flex;
+    align-items: center;
+    background: #2d2d2d;
+    color: white;
+    border: 1px solid #404040;
+    border-radius: 4px;
+    padding: 4px 8px;
+    font-size: 0.8em;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.copy-button:hover {
+    background: #404040;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+}
+
+.tooltip {
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    transform: translateX(-50%);
+    background: black;
+    color: white;
+    padding: 4px 8px;
+    border-radius: 4px;
+    font-size: 12px;
+    display: none;
+}
+
+.tooltip::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 5px solid transparent;
+    border-top-color: black;
+}
+
+.copy-button.copied .tooltip {
+    display: block;
+}
+
+.code-content {
+    margin: 0;
+    padding: 0;
+}
+
+.code-content pre {
+    margin: 0;
+    padding: 10px;
+}
+</style>
+
+<div class="code-block-container" data-lang="{{ $lang }}">
+    <div class="code-header">
+        <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
+                <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
+            </svg>
+            <span>Copy</span>
+            <div class="tooltip">Copied!</div>
+        </button>
+    </div>
+    <div class="code-content">
+        {{ highlight (trim .Inner "\n") $lang "" }}
+    </div>
+</div>
+
+<script>
+function copyCodeBlock(button) {
+    const container = button.closest('.code-block-container');
+    const codeContent = container.querySelector('.code-content pre');
+    const code = codeContent.textContent;
+    
+    navigator.clipboard.writeText(code.trim()).then(() => {
+        button.classList.add('copied');
+        setTimeout(() => {
+            button.classList.remove('copied');
+        }, 2000);
+    }).catch(err => {
+        console.error('Failed to copy:', err);
+        // Fallback
+        const textarea = document.createElement('textarea');
+        textarea.value = code.trim();
+        document.body.appendChild(textarea);
+        textarea.select();
+        try {
+            document.execCommand('copy');
+            button.classList.add('copied');
+            setTimeout(() => {
+                button.classList.remove('copied');
+            }, 2000);
+        } catch (e) {
+            console.error('Fallback failed:', e);
+        }
+        document.body.removeChild(textarea);
+    });
+}
+</script> 

+ 89 - 0
public/css/code-copy.css

@@ -0,0 +1,89 @@
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    background: #1e1e1e;
+}
+
+.code-header {
+    position: absolute;
+    top: 0.5rem;
+    right: 0.5rem !important;
+    z-index: 20;
+}
+
+.copy-button {
+    background: #2d2d2d !important;
+    border: 1px solid #404040 !important;
+    cursor: pointer;
+    padding: 0.4rem 0.8rem;
+    display: flex;
+    align-items: center;
+    gap: 0.5rem;
+    color: #ffffff !important;
+    border-radius: 4px;
+    transition: all 0.2s ease;
+    font-size: 0.85em;
+    line-height: 1;
+    min-height: 32px;
+}
+
+.copy-button:hover {
+    background-color: #404040 !important;
+    border-color: #505050 !important;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    stroke: currentColor;
+}
+
+.copy-button .button-text {
+    color: #ffffff !important;
+}
+
+.copy-button .tooltip {
+    visibility: hidden;
+    position: absolute;
+    top: -2.5rem;
+    left: 50%;
+    transform: translateX(-50%);
+    background: #000000;
+    color: #ffffff;
+    padding: 0.4rem 0.8rem;
+    border-radius: 4px;
+    font-size: 0.75rem;
+    white-space: nowrap;
+    opacity: 0;
+    transition: opacity 0.2s ease, visibility 0.2s ease;
+    pointer-events: none;
+    z-index: 30;
+}
+
+.copy-button.copied .tooltip {
+    visibility: visible;
+    opacity: 1;
+}
+
+.copy-button.copied {
+    background-color: #1a4721 !important;
+    border-color: #2ea043 !important;
+    color: #3fb950 !important;
+}
+
+.code-content {
+    position: relative;
+    overflow-x: auto;
+    padding: 1rem;
+}
+
+.copy-button .tooltip::after {
+    content: '';
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border-width: 5px;
+    border-style: solid;
+    border-color: #000000 transparent transparent transparent;
+} 

+ 40 - 0
public/js/code-copy.js

@@ -0,0 +1,40 @@
+function copyCode(button) {
+    const codeBlock = button.closest('.code-block-container').querySelector('.code-content');
+    // Get the actual code content, excluding any highlight tags
+    const preElement = codeBlock.querySelector('pre');
+    const code = preElement ? preElement.textContent : codeBlock.textContent;
+    const tooltip = button.querySelector('.tooltip');
+
+    // Create a temporary textarea to copy the text
+    const textarea = document.createElement('textarea');
+    textarea.value = code.trim();
+    document.body.appendChild(textarea);
+    textarea.select();
+
+    try {
+        document.execCommand('copy');
+        button.classList.add('copied');
+        tooltip.textContent = 'Copied!';
+        
+        // Fallback to modern clipboard API if available
+        if (navigator.clipboard) {
+            navigator.clipboard.writeText(code.trim()).catch(() => {});
+        }
+
+        setTimeout(() => {
+            button.classList.remove('copied');
+            tooltip.textContent = '';
+        }, 2000);
+    } catch (err) {
+        console.error('Failed to copy:', err);
+        tooltip.textContent = 'Failed to copy';
+        button.classList.add('copied');
+        
+        setTimeout(() => {
+            button.classList.remove('copied');
+            tooltip.textContent = '';
+        }, 2000);
+    } finally {
+        document.body.removeChild(textarea);
+    }
+} 

+ 755 - 8
public/posts/2024/git_ssh_command/index.html

@@ -113,20 +113,517 @@ Configuring SSH Keys for Individual Git Commands | codeskraps
 <h2 id="the-solution">The Solution</h2>
 <h2 id="the-solution">The Solution</h2>
 <p>Git provides a handy way to set configuration options for a single command using the <code>-c</code> flag. This allows you to specify the SSH command to use, including the path to your private key file.</p>
 <p>Git provides a handy way to set configuration options for a single command using the <code>-c</code> flag. This allows you to specify the SSH command to use, including the path to your private key file.</p>
 <p>Here&rsquo;s the syntax:</p>
 <p>Here&rsquo;s the syntax:</p>
-<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git -c core.sshCommand<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#34;ssh -i /path/to/private_key_file&#34;</span> &lt;git command&gt;</span></span></code></pre></div>
+
+<style>
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    border: 1px solid #5E5E5E;
+    border-radius: 1px;
+    overflow: hidden;
+}
+
+.code-header {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    z-index: 999;
+}
+
+.copy-button {
+    display: inline-flex;
+    align-items: center;
+    background: #2d2d2d;
+    color: white;
+    border: 1px solid #404040;
+    border-radius: 4px;
+    padding: 4px 8px;
+    font-size: 0.8em;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.copy-button:hover {
+    background: #404040;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+}
+
+.tooltip {
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    transform: translateX(-50%);
+    background: black;
+    color: white;
+    padding: 4px 8px;
+    border-radius: 4px;
+    font-size: 12px;
+    display: none;
+}
+
+.tooltip::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 5px solid transparent;
+    border-top-color: black;
+}
+
+.copy-button.copied .tooltip {
+    display: block;
+}
+
+.code-content {
+    margin: 0;
+    padding: 0;
+}
+
+.code-content pre {
+    margin: 0;
+    padding: 10px;
+}
+</style>
+
+<div class="code-block-container" data-lang="bash">
+    <div class="code-header">
+        <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
+                <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
+            </svg>
+            <span>Copy</span>
+            <div class="tooltip">Copied!</div>
+        </button>
+    </div>
+    <div class="code-content">
+        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git -c core.sshCommand<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#34;ssh -i /path/to/private_key_file&#34;</span> &lt;git command&gt;</span></span></code></pre></div>
+    </div>
+</div>
+
+<script>
+function copyCodeBlock(button) {
+    const container = button.closest('.code-block-container');
+    const codeContent = container.querySelector('.code-content pre');
+    const code = codeContent.textContent;
+    
+    navigator.clipboard.writeText(code.trim()).then(() => {
+        button.classList.add('copied');
+        setTimeout(() => {
+            button.classList.remove('copied');
+        }, 2000);
+    }).catch(err => {
+        console.error('Failed to copy:', err);
+        
+        const textarea = document.createElement('textarea');
+        textarea.value = code.trim();
+        document.body.appendChild(textarea);
+        textarea.select();
+        try {
+            document.execCommand('copy');
+            button.classList.add('copied');
+            setTimeout(() => {
+                button.classList.remove('copied');
+            }, 2000);
+        } catch (e) {
+            console.error('Fallback failed:', e);
+        }
+        document.body.removeChild(textarea);
+    });
+}
+</script> 
 <h2 id="examples">Examples</h2>
 <h2 id="examples">Examples</h2>
 <h3 id="cloning-a-repository">Cloning a Repository</h3>
 <h3 id="cloning-a-repository">Cloning a Repository</h3>
 <p>To clone a repository using a specific SSH key:</p>
 <p>To clone a repository using a specific SSH key:</p>
-<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git -c core.sshCommand<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#34;ssh -i /path/to/private_key_file&#34;</span> clone git@github.com:username/repo.git</span></span></code></pre></div>
+
+<style>
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    border: 1px solid #5E5E5E;
+    border-radius: 1px;
+    overflow: hidden;
+}
+
+.code-header {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    z-index: 999;
+}
+
+.copy-button {
+    display: inline-flex;
+    align-items: center;
+    background: #2d2d2d;
+    color: white;
+    border: 1px solid #404040;
+    border-radius: 4px;
+    padding: 4px 8px;
+    font-size: 0.8em;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.copy-button:hover {
+    background: #404040;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+}
+
+.tooltip {
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    transform: translateX(-50%);
+    background: black;
+    color: white;
+    padding: 4px 8px;
+    border-radius: 4px;
+    font-size: 12px;
+    display: none;
+}
+
+.tooltip::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 5px solid transparent;
+    border-top-color: black;
+}
+
+.copy-button.copied .tooltip {
+    display: block;
+}
+
+.code-content {
+    margin: 0;
+    padding: 0;
+}
+
+.code-content pre {
+    margin: 0;
+    padding: 10px;
+}
+</style>
+
+<div class="code-block-container" data-lang="bash">
+    <div class="code-header">
+        <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
+                <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
+            </svg>
+            <span>Copy</span>
+            <div class="tooltip">Copied!</div>
+        </button>
+    </div>
+    <div class="code-content">
+        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git -c core.sshCommand<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#34;ssh -i /path/to/private_key_file&#34;</span> clone git@github.com:username/repo.git</span></span></code></pre></div>
+    </div>
+</div>
+
+<script>
+function copyCodeBlock(button) {
+    const container = button.closest('.code-block-container');
+    const codeContent = container.querySelector('.code-content pre');
+    const code = codeContent.textContent;
+    
+    navigator.clipboard.writeText(code.trim()).then(() => {
+        button.classList.add('copied');
+        setTimeout(() => {
+            button.classList.remove('copied');
+        }, 2000);
+    }).catch(err => {
+        console.error('Failed to copy:', err);
+        
+        const textarea = document.createElement('textarea');
+        textarea.value = code.trim();
+        document.body.appendChild(textarea);
+        textarea.select();
+        try {
+            document.execCommand('copy');
+            button.classList.add('copied');
+            setTimeout(() => {
+                button.classList.remove('copied');
+            }, 2000);
+        } catch (e) {
+            console.error('Fallback failed:', e);
+        }
+        document.body.removeChild(textarea);
+    });
+}
+</script> 
 <h3 id="adding-a-submodule">Adding a Submodule</h3>
 <h3 id="adding-a-submodule">Adding a Submodule</h3>
 <p>Similarly, when adding a submodule:</p>
 <p>Similarly, when adding a submodule:</p>
-<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git -c core.sshCommand<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#34;ssh -i /path/to/private_key_file&#34;</span> submodule add git@github.com:username/submodule.git</span></span></code></pre></div>
+
+<style>
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    border: 1px solid #5E5E5E;
+    border-radius: 1px;
+    overflow: hidden;
+}
+
+.code-header {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    z-index: 999;
+}
+
+.copy-button {
+    display: inline-flex;
+    align-items: center;
+    background: #2d2d2d;
+    color: white;
+    border: 1px solid #404040;
+    border-radius: 4px;
+    padding: 4px 8px;
+    font-size: 0.8em;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.copy-button:hover {
+    background: #404040;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+}
+
+.tooltip {
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    transform: translateX(-50%);
+    background: black;
+    color: white;
+    padding: 4px 8px;
+    border-radius: 4px;
+    font-size: 12px;
+    display: none;
+}
+
+.tooltip::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 5px solid transparent;
+    border-top-color: black;
+}
+
+.copy-button.copied .tooltip {
+    display: block;
+}
+
+.code-content {
+    margin: 0;
+    padding: 0;
+}
+
+.code-content pre {
+    margin: 0;
+    padding: 10px;
+}
+</style>
+
+<div class="code-block-container" data-lang="bash">
+    <div class="code-header">
+        <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
+                <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
+            </svg>
+            <span>Copy</span>
+            <div class="tooltip">Copied!</div>
+        </button>
+    </div>
+    <div class="code-content">
+        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git -c core.sshCommand<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#34;ssh -i /path/to/private_key_file&#34;</span> submodule add git@github.com:username/submodule.git</span></span></code></pre></div>
+    </div>
+</div>
+
+<script>
+function copyCodeBlock(button) {
+    const container = button.closest('.code-block-container');
+    const codeContent = container.querySelector('.code-content pre');
+    const code = codeContent.textContent;
+    
+    navigator.clipboard.writeText(code.trim()).then(() => {
+        button.classList.add('copied');
+        setTimeout(() => {
+            button.classList.remove('copied');
+        }, 2000);
+    }).catch(err => {
+        console.error('Failed to copy:', err);
+        
+        const textarea = document.createElement('textarea');
+        textarea.value = code.trim();
+        document.body.appendChild(textarea);
+        textarea.select();
+        try {
+            document.execCommand('copy');
+            button.classList.add('copied');
+            setTimeout(() => {
+                button.classList.remove('copied');
+            }, 2000);
+        } catch (e) {
+            console.error('Fallback failed:', e);
+        }
+        document.body.removeChild(textarea);
+    });
+}
+</script> 
 <h2 id="making-ssh-keys-available">Making SSH Keys Available</h2>
 <h2 id="making-ssh-keys-available">Making SSH Keys Available</h2>
 <p>Before using SSH keys with Git, it&rsquo;s important to check which keys are already available on your system:</p>
 <p>Before using SSH keys with Git, it&rsquo;s important to check which keys are already available on your system:</p>
 <ol>
 <ol>
 <li>
 <li>
 <p><strong>Check Available Keys</strong>: List the contents of your SSH directory:
 <p><strong>Check Available Keys</strong>: List the contents of your SSH directory:
-<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ls -al ~/.ssh</span></span></code></pre></div>
+
+<style>
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    border: 1px solid #5E5E5E;
+    border-radius: 1px;
+    overflow: hidden;
+}
+
+.code-header {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    z-index: 999;
+}
+
+.copy-button {
+    display: inline-flex;
+    align-items: center;
+    background: #2d2d2d;
+    color: white;
+    border: 1px solid #404040;
+    border-radius: 4px;
+    padding: 4px 8px;
+    font-size: 0.8em;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.copy-button:hover {
+    background: #404040;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+}
+
+.tooltip {
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    transform: translateX(-50%);
+    background: black;
+    color: white;
+    padding: 4px 8px;
+    border-radius: 4px;
+    font-size: 12px;
+    display: none;
+}
+
+.tooltip::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 5px solid transparent;
+    border-top-color: black;
+}
+
+.copy-button.copied .tooltip {
+    display: block;
+}
+
+.code-content {
+    margin: 0;
+    padding: 0;
+}
+
+.code-content pre {
+    margin: 0;
+    padding: 10px;
+}
+</style>
+
+<div class="code-block-container" data-lang="bash">
+    <div class="code-header">
+        <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
+                <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
+            </svg>
+            <span>Copy</span>
+            <div class="tooltip">Copied!</div>
+        </button>
+    </div>
+    <div class="code-content">
+        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>   ls -al ~/.ssh
+</span></span><span style="display:flex;"><span>   </span></span></code></pre></div>
+    </div>
+</div>
+
+<script>
+function copyCodeBlock(button) {
+    const container = button.closest('.code-block-container');
+    const codeContent = container.querySelector('.code-content pre');
+    const code = codeContent.textContent;
+    
+    navigator.clipboard.writeText(code.trim()).then(() => {
+        button.classList.add('copied');
+        setTimeout(() => {
+            button.classList.remove('copied');
+        }, 2000);
+    }).catch(err => {
+        console.error('Failed to copy:', err);
+        
+        const textarea = document.createElement('textarea');
+        textarea.value = code.trim();
+        document.body.appendChild(textarea);
+        textarea.select();
+        try {
+            document.execCommand('copy');
+            button.classList.add('copied');
+            setTimeout(() => {
+                button.classList.remove('copied');
+            }, 2000);
+        } catch (e) {
+            console.error('Fallback failed:', e);
+        }
+        document.body.removeChild(textarea);
+    });
+}
+</script> 
 This command will show you all files in your SSH directory, including your key files (typically with extensions like .pub for public keys).</p>
 This command will show you all files in your SSH directory, including your key files (typically with extensions like .pub for public keys).</p>
 </li>
 </li>
 <li>
 <li>
@@ -139,8 +636,133 @@ This command will show you all files in your SSH directory, including your key f
 </li>
 </li>
 <li>
 <li>
 <p><strong>Add to SSH Agent</strong>: If you find the key you want to use, ensure it&rsquo;s added to your SSH agent:
 <p><strong>Add to SSH Agent</strong>: If you find the key you want to use, ensure it&rsquo;s added to your SSH agent:
-<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">eval</span> <span style="color:#f1fa8c">&#34;</span><span style="color:#ff79c6">$(</span>ssh-agent -s<span style="color:#ff79c6">)</span><span style="color:#f1fa8c">&#34;</span>
-</span></span><span style="display:flex;"><span>ssh-add ~/.ssh/your_private_key_file</span></span></code></pre></div></p>
+
+<style>
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    border: 1px solid #5E5E5E;
+    border-radius: 1px;
+    overflow: hidden;
+}
+
+.code-header {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    z-index: 999;
+}
+
+.copy-button {
+    display: inline-flex;
+    align-items: center;
+    background: #2d2d2d;
+    color: white;
+    border: 1px solid #404040;
+    border-radius: 4px;
+    padding: 4px 8px;
+    font-size: 0.8em;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.copy-button:hover {
+    background: #404040;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+}
+
+.tooltip {
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    transform: translateX(-50%);
+    background: black;
+    color: white;
+    padding: 4px 8px;
+    border-radius: 4px;
+    font-size: 12px;
+    display: none;
+}
+
+.tooltip::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 5px solid transparent;
+    border-top-color: black;
+}
+
+.copy-button.copied .tooltip {
+    display: block;
+}
+
+.code-content {
+    margin: 0;
+    padding: 0;
+}
+
+.code-content pre {
+    margin: 0;
+    padding: 10px;
+}
+</style>
+
+<div class="code-block-container" data-lang="bash">
+    <div class="code-header">
+        <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
+                <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
+            </svg>
+            <span>Copy</span>
+            <div class="tooltip">Copied!</div>
+        </button>
+    </div>
+    <div class="code-content">
+        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>   <span style="color:#8be9fd;font-style:italic">eval</span> <span style="color:#f1fa8c">&#34;</span><span style="color:#ff79c6">$(</span>ssh-agent -s<span style="color:#ff79c6">)</span><span style="color:#f1fa8c">&#34;</span>
+</span></span><span style="display:flex;"><span>   ssh-add ~/.ssh/your_private_key_file
+</span></span><span style="display:flex;"><span>   </span></span></code></pre></div>
+    </div>
+</div>
+
+<script>
+function copyCodeBlock(button) {
+    const container = button.closest('.code-block-container');
+    const codeContent = container.querySelector('.code-content pre');
+    const code = codeContent.textContent;
+    
+    navigator.clipboard.writeText(code.trim()).then(() => {
+        button.classList.add('copied');
+        setTimeout(() => {
+            button.classList.remove('copied');
+        }, 2000);
+    }).catch(err => {
+        console.error('Failed to copy:', err);
+        
+        const textarea = document.createElement('textarea');
+        textarea.value = code.trim();
+        document.body.appendChild(textarea);
+        textarea.select();
+        try {
+            document.execCommand('copy');
+            button.classList.add('copied');
+            setTimeout(() => {
+                button.classList.remove('copied');
+            }, 2000);
+        } catch (e) {
+            console.error('Fallback failed:', e);
+        }
+        document.body.removeChild(textarea);
+    });
+}
+</script> </p>
 </li>
 </li>
 <li>
 <li>
 <p><strong>Verify Key in Git Host</strong>: Make sure the corresponding public key (the .pub file) is added to your Git host (e.g., GitHub, GitLab) in the SSH keys section of your account settings.</p>
 <p><strong>Verify Key in Git Host</strong>: Make sure the corresponding public key (the .pub file) is added to your Git host (e.g., GitHub, GitLab) in the SSH keys section of your account settings.</p>
@@ -158,8 +780,133 @@ This command will show you all files in your SSH directory, including your key f
 </li>
 </li>
 <li>
 <li>
 <p>Add the following lines under the <code>[core]</code> section (or create it if it doesn&rsquo;t exist):</p>
 <p>Add the following lines under the <code>[core]</code> section (or create it if it doesn&rsquo;t exist):</p>
-<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ini" data-lang="ini"><span style="display:flex;"><span><span style="color:#ff79c6">[core]</span>
-</span></span><span style="display:flex;"><span>    <span style="color:#50fa7b">sshCommand</span> <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">ssh -i /path/to/private_key_file</span></span></span></code></pre></div>
+
+<style>
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    border: 1px solid #5E5E5E;
+    border-radius: 1px;
+    overflow: hidden;
+}
+
+.code-header {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    z-index: 999;
+}
+
+.copy-button {
+    display: inline-flex;
+    align-items: center;
+    background: #2d2d2d;
+    color: white;
+    border: 1px solid #404040;
+    border-radius: 4px;
+    padding: 4px 8px;
+    font-size: 0.8em;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.copy-button:hover {
+    background: #404040;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+}
+
+.tooltip {
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    transform: translateX(-50%);
+    background: black;
+    color: white;
+    padding: 4px 8px;
+    border-radius: 4px;
+    font-size: 12px;
+    display: none;
+}
+
+.tooltip::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 5px solid transparent;
+    border-top-color: black;
+}
+
+.copy-button.copied .tooltip {
+    display: block;
+}
+
+.code-content {
+    margin: 0;
+    padding: 0;
+}
+
+.code-content pre {
+    margin: 0;
+    padding: 10px;
+}
+</style>
+
+<div class="code-block-container" data-lang="ini">
+    <div class="code-header">
+        <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
+                <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
+            </svg>
+            <span>Copy</span>
+            <div class="tooltip">Copied!</div>
+        </button>
+    </div>
+    <div class="code-content">
+        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ini" data-lang="ini"><span style="display:flex;"><span>   <span style="color:#ff79c6">[core]</span>
+</span></span><span style="display:flex;"><span>       <span style="color:#50fa7b">sshCommand</span> <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">ssh -i /path/to/private_key_file
+</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">   </span></span></span></code></pre></div>
+    </div>
+</div>
+
+<script>
+function copyCodeBlock(button) {
+    const container = button.closest('.code-block-container');
+    const codeContent = container.querySelector('.code-content pre');
+    const code = codeContent.textContent;
+    
+    navigator.clipboard.writeText(code.trim()).then(() => {
+        button.classList.add('copied');
+        setTimeout(() => {
+            button.classList.remove('copied');
+        }, 2000);
+    }).catch(err => {
+        console.error('Failed to copy:', err);
+        
+        const textarea = document.createElement('textarea');
+        textarea.value = code.trim();
+        document.body.appendChild(textarea);
+        textarea.select();
+        try {
+            document.execCommand('copy');
+            button.classList.add('copied');
+            setTimeout(() => {
+                button.classList.remove('copied');
+            }, 2000);
+        } catch (e) {
+            console.error('Fallback failed:', e);
+        }
+        document.body.removeChild(textarea);
+    });
+}
+</script> 
 </li>
 </li>
 <li>
 <li>
 <p>Save and close the file.</p>
 <p>Save and close the file.</p>

+ 127 - 2
public/posts/2024/gitignore_not_working/index.html

@@ -120,8 +120,133 @@ When .gitignore Doesnt Seem to Work: A Quick Fix | codeskraps
 </li>
 </li>
 <li>
 <li>
 <p>Then, run these two commands:</p>
 <p>Then, run these two commands:</p>
-<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git rm -rf --cached .
-</span></span><span style="display:flex;"><span>git add .</span></span></code></pre></div>
+
+<style>
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    border: 1px solid #5E5E5E;
+    border-radius: 1px;
+    overflow: hidden;
+}
+
+.code-header {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    z-index: 999;
+}
+
+.copy-button {
+    display: inline-flex;
+    align-items: center;
+    background: #2d2d2d;
+    color: white;
+    border: 1px solid #404040;
+    border-radius: 4px;
+    padding: 4px 8px;
+    font-size: 0.8em;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.copy-button:hover {
+    background: #404040;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+}
+
+.tooltip {
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    transform: translateX(-50%);
+    background: black;
+    color: white;
+    padding: 4px 8px;
+    border-radius: 4px;
+    font-size: 12px;
+    display: none;
+}
+
+.tooltip::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 5px solid transparent;
+    border-top-color: black;
+}
+
+.copy-button.copied .tooltip {
+    display: block;
+}
+
+.code-content {
+    margin: 0;
+    padding: 0;
+}
+
+.code-content pre {
+    margin: 0;
+    padding: 10px;
+}
+</style>
+
+<div class="code-block-container" data-lang="bash">
+    <div class="code-header">
+        <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
+                <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
+            </svg>
+            <span>Copy</span>
+            <div class="tooltip">Copied!</div>
+        </button>
+    </div>
+    <div class="code-content">
+        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>   git rm -rf --cached .
+</span></span><span style="display:flex;"><span>   git add .
+</span></span><span style="display:flex;"><span>   </span></span></code></pre></div>
+    </div>
+</div>
+
+<script>
+function copyCodeBlock(button) {
+    const container = button.closest('.code-block-container');
+    const codeContent = container.querySelector('.code-content pre');
+    const code = codeContent.textContent;
+    
+    navigator.clipboard.writeText(code.trim()).then(() => {
+        button.classList.add('copied');
+        setTimeout(() => {
+            button.classList.remove('copied');
+        }, 2000);
+    }).catch(err => {
+        console.error('Failed to copy:', err);
+        
+        const textarea = document.createElement('textarea');
+        textarea.value = code.trim();
+        document.body.appendChild(textarea);
+        textarea.select();
+        try {
+            document.execCommand('copy');
+            button.classList.add('copied');
+            setTimeout(() => {
+                button.classList.remove('copied');
+            }, 2000);
+        } catch (e) {
+            console.error('Fallback failed:', e);
+        }
+        document.body.removeChild(textarea);
+    });
+}
+</script> 
 </li>
 </li>
 </ol>
 </ol>
 <p>Let&rsquo;s break down what these commands do:</p>
 <p>Let&rsquo;s break down what these commands do:</p>

+ 375 - 3
public/posts/2024/mvi_architecture/index.html

@@ -115,7 +115,97 @@ Simplifying MVI Architecture | codeskraps
         <p>Model-View-Intent (MVI) is a powerful architectural pattern for building user interfaces, especially in Android development. In this post, we&rsquo;ll explore a helper class that simplifies the implementation of MVI, making it easier to manage state, handle user intents, and emit actions in your application.</p>
         <p>Model-View-Intent (MVI) is a powerful architectural pattern for building user interfaces, especially in Android development. In this post, we&rsquo;ll explore a helper class that simplifies the implementation of MVI, making it easier to manage state, handle user intents, and emit actions in your application.</p>
 <h2 id="the-mvi-helper-class">The MVI Helper Class</h2>
 <h2 id="the-mvi-helper-class">The MVI Helper Class</h2>
 <p>First, let&rsquo;s look at the complete helper class:</p>
 <p>First, let&rsquo;s look at the complete helper class:</p>
-<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-kotlin" data-lang="kotlin"><span style="display:flex;"><span><span style="color:#ff79c6">interface</span> <span style="color:#50fa7b">StateReceiver</span>&lt;STATE&gt; {
+
+<style>
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    border: 1px solid #5E5E5E;
+    border-radius: 1px;
+    overflow: hidden;
+}
+
+.code-header {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    z-index: 999;
+}
+
+.copy-button {
+    display: inline-flex;
+    align-items: center;
+    background: #2d2d2d;
+    color: white;
+    border: 1px solid #404040;
+    border-radius: 4px;
+    padding: 4px 8px;
+    font-size: 0.8em;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.copy-button:hover {
+    background: #404040;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+}
+
+.tooltip {
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    transform: translateX(-50%);
+    background: black;
+    color: white;
+    padding: 4px 8px;
+    border-radius: 4px;
+    font-size: 12px;
+    display: none;
+}
+
+.tooltip::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 5px solid transparent;
+    border-top-color: black;
+}
+
+.copy-button.copied .tooltip {
+    display: block;
+}
+
+.code-content {
+    margin: 0;
+    padding: 0;
+}
+
+.code-content pre {
+    margin: 0;
+    padding: 10px;
+}
+</style>
+
+<div class="code-block-container" data-lang="kotlin">
+    <div class="code-header">
+        <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
+                <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
+            </svg>
+            <span>Copy</span>
+            <div class="tooltip">Copied!</div>
+        </button>
+    </div>
+    <div class="code-content">
+        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-kotlin" data-lang="kotlin"><span style="display:flex;"><span><span style="color:#ff79c6">interface</span> <span style="color:#50fa7b">StateReceiver</span>&lt;STATE&gt; {
 </span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">suspend</span> <span style="color:#ff79c6">fun</span> <span style="color:#50fa7b">updateState</span>(transform: <span style="color:#ff79c6">suspend</span> (STATE) <span style="color:#ff79c6">-&gt;</span> STATE)
 </span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">suspend</span> <span style="color:#ff79c6">fun</span> <span style="color:#50fa7b">updateState</span>(transform: <span style="color:#ff79c6">suspend</span> (STATE) <span style="color:#ff79c6">-&gt;</span> STATE)
 </span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">suspend</span> <span style="color:#ff79c6">fun</span> <span style="color:#50fa7b">withState</span>(block: <span style="color:#ff79c6">suspend</span> (STATE) <span style="color:#ff79c6">-&gt;</span> Unit)
 </span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">suspend</span> <span style="color:#ff79c6">fun</span> <span style="color:#50fa7b">withState</span>(block: <span style="color:#ff79c6">suspend</span> (STATE) <span style="color:#ff79c6">-&gt;</span> Unit)
 </span></span><span style="display:flex;"><span>}
 </span></span><span style="display:flex;"><span>}
@@ -185,6 +275,40 @@ Simplifying MVI Architecture | codeskraps
 </span></span><span style="display:flex;"><span>        <span style="color:#ff79c6">throw</span> NotImplementedError()
 </span></span><span style="display:flex;"><span>        <span style="color:#ff79c6">throw</span> NotImplementedError()
 </span></span><span style="display:flex;"><span>    }
 </span></span><span style="display:flex;"><span>    }
 </span></span><span style="display:flex;"><span>}</span></span></code></pre></div>
 </span></span><span style="display:flex;"><span>}</span></span></code></pre></div>
+    </div>
+</div>
+
+<script>
+function copyCodeBlock(button) {
+    const container = button.closest('.code-block-container');
+    const codeContent = container.querySelector('.code-content pre');
+    const code = codeContent.textContent;
+    
+    navigator.clipboard.writeText(code.trim()).then(() => {
+        button.classList.add('copied');
+        setTimeout(() => {
+            button.classList.remove('copied');
+        }, 2000);
+    }).catch(err => {
+        console.error('Failed to copy:', err);
+        
+        const textarea = document.createElement('textarea');
+        textarea.value = code.trim();
+        document.body.appendChild(textarea);
+        textarea.select();
+        try {
+            document.execCommand('copy');
+            button.classList.add('copied');
+            setTimeout(() => {
+                button.classList.remove('copied');
+            }, 2000);
+        } catch (e) {
+            console.error('Fallback failed:', e);
+        }
+        document.body.removeChild(textarea);
+    });
+}
+</script> 
 <h2 id="understanding-the-mvi-helper-class">Understanding the MVI Helper Class</h2>
 <h2 id="understanding-the-mvi-helper-class">Understanding the MVI Helper Class</h2>
 <p>Let&rsquo;s break down the key components of our MVI helper class:</p>
 <p>Let&rsquo;s break down the key components of our MVI helper class:</p>
 <h3 id="core-interfaces">Core Interfaces</h3>
 <h3 id="core-interfaces">Core Interfaces</h3>
@@ -211,7 +335,97 @@ Simplifying MVI Architecture | codeskraps
 <p>This class implements the <code>MVIViewModel</code> interface, providing a concrete implementation of the MVI pattern.</p>
 <p>This class implements the <code>MVIViewModel</code> interface, providing a concrete implementation of the MVI pattern.</p>
 <h2 id="example-implementation">Example Implementation</h2>
 <h2 id="example-implementation">Example Implementation</h2>
 <p>Let&rsquo;s implement a simple counter application using our MVI helper class. Note that we can use either data classes or sealed interfaces for our State, Intent, and Action definitions:</p>
 <p>Let&rsquo;s implement a simple counter application using our MVI helper class. Note that we can use either data classes or sealed interfaces for our State, Intent, and Action definitions:</p>
-<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-kotlin" data-lang="kotlin"><span style="display:flex;"><span><span style="color:#6272a4">// Define our State, Intent, and Action
+
+<style>
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    border: 1px solid #5E5E5E;
+    border-radius: 1px;
+    overflow: hidden;
+}
+
+.code-header {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    z-index: 999;
+}
+
+.copy-button {
+    display: inline-flex;
+    align-items: center;
+    background: #2d2d2d;
+    color: white;
+    border: 1px solid #404040;
+    border-radius: 4px;
+    padding: 4px 8px;
+    font-size: 0.8em;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.copy-button:hover {
+    background: #404040;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+}
+
+.tooltip {
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    transform: translateX(-50%);
+    background: black;
+    color: white;
+    padding: 4px 8px;
+    border-radius: 4px;
+    font-size: 12px;
+    display: none;
+}
+
+.tooltip::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 5px solid transparent;
+    border-top-color: black;
+}
+
+.copy-button.copied .tooltip {
+    display: block;
+}
+
+.code-content {
+    margin: 0;
+    padding: 0;
+}
+
+.code-content pre {
+    margin: 0;
+    padding: 10px;
+}
+</style>
+
+<div class="code-block-container" data-lang="kotlin">
+    <div class="code-header">
+        <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
+                <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
+            </svg>
+            <span>Copy</span>
+            <div class="tooltip">Copied!</div>
+        </button>
+    </div>
+    <div class="code-content">
+        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-kotlin" data-lang="kotlin"><span style="display:flex;"><span><span style="color:#6272a4">// Define our State, Intent, and Action
 </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span><span style="color:#ff79c6">data</span> <span style="color:#ff79c6">class</span> <span style="color:#50fa7b">CounterState</span>(<span style="color:#ff79c6">val</span> count: Int = <span style="color:#bd93f9">0</span>)
 </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span><span style="color:#ff79c6">data</span> <span style="color:#ff79c6">class</span> <span style="color:#50fa7b">CounterState</span>(<span style="color:#ff79c6">val</span> count: Int = <span style="color:#bd93f9">0</span>)
 </span></span><span style="display:flex;"><span>
 </span></span><span style="display:flex;"><span>
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">sealed</span> <span style="color:#ff79c6">interface</span> <span style="color:#50fa7b">CounterIntent</span> {
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">sealed</span> <span style="color:#ff79c6">interface</span> <span style="color:#50fa7b">CounterIntent</span> {
@@ -245,6 +459,40 @@ Simplifying MVI Architecture | codeskraps
 </span></span><span style="display:flex;"><span>        }
 </span></span><span style="display:flex;"><span>        }
 </span></span><span style="display:flex;"><span>    }
 </span></span><span style="display:flex;"><span>    }
 </span></span><span style="display:flex;"><span>}</span></span></code></pre></div>
 </span></span><span style="display:flex;"><span>}</span></span></code></pre></div>
+    </div>
+</div>
+
+<script>
+function copyCodeBlock(button) {
+    const container = button.closest('.code-block-container');
+    const codeContent = container.querySelector('.code-content pre');
+    const code = codeContent.textContent;
+    
+    navigator.clipboard.writeText(code.trim()).then(() => {
+        button.classList.add('copied');
+        setTimeout(() => {
+            button.classList.remove('copied');
+        }, 2000);
+    }).catch(err => {
+        console.error('Failed to copy:', err);
+        
+        const textarea = document.createElement('textarea');
+        textarea.value = code.trim();
+        document.body.appendChild(textarea);
+        textarea.select();
+        try {
+            document.execCommand('copy');
+            button.classList.add('copied');
+            setTimeout(() => {
+                button.classList.remove('copied');
+            }, 2000);
+        } catch (e) {
+            console.error('Fallback failed:', e);
+        }
+        document.body.removeChild(textarea);
+    });
+}
+</script> 
 <p>In this example:</p>
 <p>In this example:</p>
 <ol>
 <ol>
 <li>We define our <code>State</code> as a data class, and our <code>Intent</code> and <code>Action</code> as sealed interfaces.</li>
 <li>We define our <code>State</code> as a data class, and our <code>Intent</code> and <code>Action</code> as sealed interfaces.</li>
@@ -254,7 +502,97 @@ Simplifying MVI Architecture | codeskraps
 </ol>
 </ol>
 <h2 id="using-the-viewmodel-in-the-ui">Using the ViewModel in the UI</h2>
 <h2 id="using-the-viewmodel-in-the-ui">Using the ViewModel in the UI</h2>
 <p>Here&rsquo;s how you might use this ViewModel in an Android Activity or Fragment:</p>
 <p>Here&rsquo;s how you might use this ViewModel in an Android Activity or Fragment:</p>
-<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-kotlin" data-lang="kotlin"><span style="display:flex;"><span><span style="color:#ff79c6">class</span> <span style="color:#50fa7b">CounterActivity</span> : AppCompatActivity() {
+
+<style>
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    border: 1px solid #5E5E5E;
+    border-radius: 1px;
+    overflow: hidden;
+}
+
+.code-header {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    z-index: 999;
+}
+
+.copy-button {
+    display: inline-flex;
+    align-items: center;
+    background: #2d2d2d;
+    color: white;
+    border: 1px solid #404040;
+    border-radius: 4px;
+    padding: 4px 8px;
+    font-size: 0.8em;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.copy-button:hover {
+    background: #404040;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+}
+
+.tooltip {
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    transform: translateX(-50%);
+    background: black;
+    color: white;
+    padding: 4px 8px;
+    border-radius: 4px;
+    font-size: 12px;
+    display: none;
+}
+
+.tooltip::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 5px solid transparent;
+    border-top-color: black;
+}
+
+.copy-button.copied .tooltip {
+    display: block;
+}
+
+.code-content {
+    margin: 0;
+    padding: 0;
+}
+
+.code-content pre {
+    margin: 0;
+    padding: 10px;
+}
+</style>
+
+<div class="code-block-container" data-lang="kotlin">
+    <div class="code-header">
+        <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
+                <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
+            </svg>
+            <span>Copy</span>
+            <div class="tooltip">Copied!</div>
+        </button>
+    </div>
+    <div class="code-content">
+        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-kotlin" data-lang="kotlin"><span style="display:flex;"><span><span style="color:#ff79c6">class</span> <span style="color:#50fa7b">CounterActivity</span> : AppCompatActivity() {
 </span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">private</span> <span style="color:#ff79c6">val</span> viewModel: CounterViewModel <span style="color:#ff79c6">by</span> viewModels()
 </span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">private</span> <span style="color:#ff79c6">val</span> viewModel: CounterViewModel <span style="color:#ff79c6">by</span> viewModels()
 </span></span><span style="display:flex;"><span>
 </span></span><span style="display:flex;"><span>
 </span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">override</span> <span style="color:#ff79c6">fun</span> <span style="color:#50fa7b">onCreate</span>(savedInstanceState: Bundle?) {
 </span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">override</span> <span style="color:#ff79c6">fun</span> <span style="color:#50fa7b">onCreate</span>(savedInstanceState: Bundle?) {
@@ -290,6 +628,40 @@ Simplifying MVI Architecture | codeskraps
 </span></span><span style="display:flex;"><span>        counterTextView.text = state.count.toString()
 </span></span><span style="display:flex;"><span>        counterTextView.text = state.count.toString()
 </span></span><span style="display:flex;"><span>    }
 </span></span><span style="display:flex;"><span>    }
 </span></span><span style="display:flex;"><span>}</span></span></code></pre></div>
 </span></span><span style="display:flex;"><span>}</span></span></code></pre></div>
+    </div>
+</div>
+
+<script>
+function copyCodeBlock(button) {
+    const container = button.closest('.code-block-container');
+    const codeContent = container.querySelector('.code-content pre');
+    const code = codeContent.textContent;
+    
+    navigator.clipboard.writeText(code.trim()).then(() => {
+        button.classList.add('copied');
+        setTimeout(() => {
+            button.classList.remove('copied');
+        }, 2000);
+    }).catch(err => {
+        console.error('Failed to copy:', err);
+        
+        const textarea = document.createElement('textarea');
+        textarea.value = code.trim();
+        document.body.appendChild(textarea);
+        textarea.select();
+        try {
+            document.execCommand('copy');
+            button.classList.add('copied');
+            setTimeout(() => {
+                button.classList.remove('copied');
+            }, 2000);
+        } catch (e) {
+            console.error('Fallback failed:', e);
+        }
+        document.body.removeChild(textarea);
+    });
+}
+</script> 
 <h2 id="conclusion">Conclusion</h2>
 <h2 id="conclusion">Conclusion</h2>
 <p>The MVI helper class we&rsquo;ve explored simplifies the implementation of the MVI pattern, providing a clean and type-safe way to manage state, handle user intents, and emit actions. By using this helper class, you can create more maintainable and testable view models, leading to more robust applications.</p>
 <p>The MVI helper class we&rsquo;ve explored simplifies the implementation of the MVI pattern, providing a clean and type-safe way to manage state, handle user intents, and emit actions. By using this helper class, you can create more maintainable and testable view models, leading to more robust applications.</p>
 <p>Remember that you can use either data classes or sealed interfaces for your State, Intent, and Action definitions, depending on your specific needs. This flexibility allows you to choose the most appropriate structure for each component of your MVI architecture.</p>
 <p>Remember that you can use either data classes or sealed interfaces for your State, Intent, and Action definitions, depending on your specific needs. This flexibility allows you to choose the most appropriate structure for each component of your MVI architecture.</p>

+ 250 - 2
public/posts/2024/react_vs_kmp/index.html

@@ -120,7 +120,97 @@ React Native vs Kotlin Multiplatform | codeskraps
 <h2 id="language-and-learning-curve">Language and Learning Curve</h2>
 <h2 id="language-and-learning-curve">Language and Learning Curve</h2>
 <h3 id="react-native-javascript-for-the-web-developer">React Native: JavaScript for the Web Developer</h3>
 <h3 id="react-native-javascript-for-the-web-developer">React Native: JavaScript for the Web Developer</h3>
 <p>React Native&rsquo;s use of JavaScript as its primary language is a significant advantage for many developers, especially those with a web development background. JavaScript&rsquo;s popularity and the vast ecosystem of tools and libraries make it an accessible choice for beginners and experienced developers alike.</p>
 <p>React Native&rsquo;s use of JavaScript as its primary language is a significant advantage for many developers, especially those with a web development background. JavaScript&rsquo;s popularity and the vast ecosystem of tools and libraries make it an accessible choice for beginners and experienced developers alike.</p>
-<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff79c6">import</span> React from <span style="color:#f1fa8c">&#39;react&#39;</span>;
+
+<style>
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    border: 1px solid #5E5E5E;
+    border-radius: 1px;
+    overflow: hidden;
+}
+
+.code-header {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    z-index: 999;
+}
+
+.copy-button {
+    display: inline-flex;
+    align-items: center;
+    background: #2d2d2d;
+    color: white;
+    border: 1px solid #404040;
+    border-radius: 4px;
+    padding: 4px 8px;
+    font-size: 0.8em;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.copy-button:hover {
+    background: #404040;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+}
+
+.tooltip {
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    transform: translateX(-50%);
+    background: black;
+    color: white;
+    padding: 4px 8px;
+    border-radius: 4px;
+    font-size: 12px;
+    display: none;
+}
+
+.tooltip::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 5px solid transparent;
+    border-top-color: black;
+}
+
+.copy-button.copied .tooltip {
+    display: block;
+}
+
+.code-content {
+    margin: 0;
+    padding: 0;
+}
+
+.code-content pre {
+    margin: 0;
+    padding: 10px;
+}
+</style>
+
+<div class="code-block-container" data-lang="javascript">
+    <div class="code-header">
+        <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
+                <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
+            </svg>
+            <span>Copy</span>
+            <div class="tooltip">Copied!</div>
+        </button>
+    </div>
+    <div class="code-content">
+        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff79c6">import</span> React from <span style="color:#f1fa8c">&#39;react&#39;</span>;
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">import</span> { Text, View } from <span style="color:#f1fa8c">&#39;react-native&#39;</span>;
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">import</span> { Text, View } from <span style="color:#f1fa8c">&#39;react-native&#39;</span>;
 </span></span><span style="display:flex;"><span>
 </span></span><span style="display:flex;"><span>
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">const</span> HelloWorldApp <span style="color:#ff79c6">=</span> () =&gt; {
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">const</span> HelloWorldApp <span style="color:#ff79c6">=</span> () =&gt; {
@@ -132,10 +222,134 @@ React Native vs Kotlin Multiplatform | codeskraps
 </span></span><span style="display:flex;"><span>}
 </span></span><span style="display:flex;"><span>}
 </span></span><span style="display:flex;"><span>
 </span></span><span style="display:flex;"><span>
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">export</span> <span style="color:#ff79c6">default</span> HelloWorldApp;</span></span></code></pre></div>
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">export</span> <span style="color:#ff79c6">default</span> HelloWorldApp;</span></span></code></pre></div>
+    </div>
+</div>
+
+<script>
+function copyCodeBlock(button) {
+    const container = button.closest('.code-block-container');
+    const codeContent = container.querySelector('.code-content pre');
+    const code = codeContent.textContent;
+    
+    navigator.clipboard.writeText(code.trim()).then(() => {
+        button.classList.add('copied');
+        setTimeout(() => {
+            button.classList.remove('copied');
+        }, 2000);
+    }).catch(err => {
+        console.error('Failed to copy:', err);
+        
+        const textarea = document.createElement('textarea');
+        textarea.value = code.trim();
+        document.body.appendChild(textarea);
+        textarea.select();
+        try {
+            document.execCommand('copy');
+            button.classList.add('copied');
+            setTimeout(() => {
+                button.classList.remove('copied');
+            }, 2000);
+        } catch (e) {
+            console.error('Fallback failed:', e);
+        }
+        document.body.removeChild(textarea);
+    });
+}
+</script> 
 <p>This familiarity can lead to faster onboarding and development cycles, particularly for teams already versed in web technologies.</p>
 <p>This familiarity can lead to faster onboarding and development cycles, particularly for teams already versed in web technologies.</p>
 <h3 id="kmp-kotlins-modern-features-at-your-fingertips">KMP: Kotlin&rsquo;s Modern Features at Your Fingertips</h3>
 <h3 id="kmp-kotlins-modern-features-at-your-fingertips">KMP: Kotlin&rsquo;s Modern Features at Your Fingertips</h3>
 <p>Kotlin Multiplatform, on the other hand, leverages the power and expressiveness of the Kotlin language. While it may have a steeper learning curve for those not familiar with Kotlin, it offers numerous benefits.</p>
 <p>Kotlin Multiplatform, on the other hand, leverages the power and expressiveness of the Kotlin language. While it may have a steeper learning curve for those not familiar with Kotlin, it offers numerous benefits.</p>
-<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-kotlin" data-lang="kotlin"><span style="display:flex;"><span><span style="color:#ff79c6">expect</span> <span style="color:#ff79c6">class</span> <span style="color:#50fa7b">Platform</span>()
+
+<style>
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    border: 1px solid #5E5E5E;
+    border-radius: 1px;
+    overflow: hidden;
+}
+
+.code-header {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    z-index: 999;
+}
+
+.copy-button {
+    display: inline-flex;
+    align-items: center;
+    background: #2d2d2d;
+    color: white;
+    border: 1px solid #404040;
+    border-radius: 4px;
+    padding: 4px 8px;
+    font-size: 0.8em;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.copy-button:hover {
+    background: #404040;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+}
+
+.tooltip {
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    transform: translateX(-50%);
+    background: black;
+    color: white;
+    padding: 4px 8px;
+    border-radius: 4px;
+    font-size: 12px;
+    display: none;
+}
+
+.tooltip::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 5px solid transparent;
+    border-top-color: black;
+}
+
+.copy-button.copied .tooltip {
+    display: block;
+}
+
+.code-content {
+    margin: 0;
+    padding: 0;
+}
+
+.code-content pre {
+    margin: 0;
+    padding: 10px;
+}
+</style>
+
+<div class="code-block-container" data-lang="kotlin">
+    <div class="code-header">
+        <button class="copy-button" onclick="copyCodeBlock(this)" aria-label="Copy code">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                <path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z"/>
+                <path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2"/>
+            </svg>
+            <span>Copy</span>
+            <div class="tooltip">Copied!</div>
+        </button>
+    </div>
+    <div class="code-content">
+        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-kotlin" data-lang="kotlin"><span style="display:flex;"><span><span style="color:#ff79c6">expect</span> <span style="color:#ff79c6">class</span> <span style="color:#50fa7b">Platform</span>()
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">expect</span> <span style="color:#ff79c6">fun</span> <span style="color:#50fa7b">Platform</span>.name(): String
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">expect</span> <span style="color:#ff79c6">fun</span> <span style="color:#50fa7b">Platform</span>.name(): String
 </span></span><span style="display:flex;"><span>
 </span></span><span style="display:flex;"><span>
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">expect</span> <span style="color:#ff79c6">fun</span> <span style="color:#50fa7b">hello</span>(): String
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">expect</span> <span style="color:#ff79c6">fun</span> <span style="color:#50fa7b">hello</span>(): String
@@ -145,6 +359,40 @@ React Native vs Kotlin Multiplatform | codeskraps
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">class</span> <span style="color:#50fa7b">Greeting</span> {
 </span></span><span style="display:flex;"><span><span style="color:#ff79c6">class</span> <span style="color:#50fa7b">Greeting</span> {
 </span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">fun</span> <span style="color:#50fa7b">greeting</span>(): String = greet()
 </span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">fun</span> <span style="color:#50fa7b">greeting</span>(): String = greet()
 </span></span><span style="display:flex;"><span>}</span></span></code></pre></div>
 </span></span><span style="display:flex;"><span>}</span></span></code></pre></div>
+    </div>
+</div>
+
+<script>
+function copyCodeBlock(button) {
+    const container = button.closest('.code-block-container');
+    const codeContent = container.querySelector('.code-content pre');
+    const code = codeContent.textContent;
+    
+    navigator.clipboard.writeText(code.trim()).then(() => {
+        button.classList.add('copied');
+        setTimeout(() => {
+            button.classList.remove('copied');
+        }, 2000);
+    }).catch(err => {
+        console.error('Failed to copy:', err);
+        
+        const textarea = document.createElement('textarea');
+        textarea.value = code.trim();
+        document.body.appendChild(textarea);
+        textarea.select();
+        try {
+            document.execCommand('copy');
+            button.classList.add('copied');
+            setTimeout(() => {
+                button.classList.remove('copied');
+            }, 2000);
+        } catch (e) {
+            console.error('Fallback failed:', e);
+        }
+        document.body.removeChild(textarea);
+    });
+}
+</script> 
 <p>These features can lead to more robust, maintainable code, which can be especially beneficial for larger, more complex projects.</p>
 <p>These features can lead to more robust, maintainable code, which can be especially beneficial for larger, more complex projects.</p>
 <h2 id="ecosystem-and-libraries">Ecosystem and Libraries</h2>
 <h2 id="ecosystem-and-libraries">Ecosystem and Libraries</h2>
 <h3 id="react-native-a-vast-universe-of-packages">React Native: A Vast Universe of Packages</h3>
 <h3 id="react-native-a-vast-universe-of-packages">React Native: A Vast Universe of Packages</h3>

File diff suppressed because it is too large
+ 1500 - 12
public/posts/2025/move_home_folder/index.html


+ 89 - 0
static/css/code-copy.css

@@ -0,0 +1,89 @@
+.code-block-container {
+    position: relative;
+    margin: 1em 0;
+    background: #1e1e1e;
+}
+
+.code-header {
+    position: absolute;
+    top: 0.5rem;
+    right: 0.5rem !important;
+    z-index: 20;
+}
+
+.copy-button {
+    background: #2d2d2d !important;
+    border: 1px solid #404040 !important;
+    cursor: pointer;
+    padding: 0.4rem 0.8rem;
+    display: flex;
+    align-items: center;
+    gap: 0.5rem;
+    color: #ffffff !important;
+    border-radius: 4px;
+    transition: all 0.2s ease;
+    font-size: 0.85em;
+    line-height: 1;
+    min-height: 32px;
+}
+
+.copy-button:hover {
+    background-color: #404040 !important;
+    border-color: #505050 !important;
+}
+
+.copy-button svg {
+    width: 14px;
+    height: 14px;
+    stroke: currentColor;
+}
+
+.copy-button .button-text {
+    color: #ffffff !important;
+}
+
+.copy-button .tooltip {
+    visibility: hidden;
+    position: absolute;
+    top: -2.5rem;
+    left: 50%;
+    transform: translateX(-50%);
+    background: #000000;
+    color: #ffffff;
+    padding: 0.4rem 0.8rem;
+    border-radius: 4px;
+    font-size: 0.75rem;
+    white-space: nowrap;
+    opacity: 0;
+    transition: opacity 0.2s ease, visibility 0.2s ease;
+    pointer-events: none;
+    z-index: 30;
+}
+
+.copy-button.copied .tooltip {
+    visibility: visible;
+    opacity: 1;
+}
+
+.copy-button.copied {
+    background-color: #1a4721 !important;
+    border-color: #2ea043 !important;
+    color: #3fb950 !important;
+}
+
+.code-content {
+    position: relative;
+    overflow-x: auto;
+    padding: 1rem;
+}
+
+.copy-button .tooltip::after {
+    content: '';
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border-width: 5px;
+    border-style: solid;
+    border-color: #000000 transparent transparent transparent;
+} 

+ 40 - 0
static/js/code-copy.js

@@ -0,0 +1,40 @@
+function copyCode(button) {
+    const codeBlock = button.closest('.code-block-container').querySelector('.code-content');
+    // Get the actual code content, excluding any highlight tags
+    const preElement = codeBlock.querySelector('pre');
+    const code = preElement ? preElement.textContent : codeBlock.textContent;
+    const tooltip = button.querySelector('.tooltip');
+
+    // Create a temporary textarea to copy the text
+    const textarea = document.createElement('textarea');
+    textarea.value = code.trim();
+    document.body.appendChild(textarea);
+    textarea.select();
+
+    try {
+        document.execCommand('copy');
+        button.classList.add('copied');
+        tooltip.textContent = 'Copied!';
+        
+        // Fallback to modern clipboard API if available
+        if (navigator.clipboard) {
+            navigator.clipboard.writeText(code.trim()).catch(() => {});
+        }
+
+        setTimeout(() => {
+            button.classList.remove('copied');
+            tooltip.textContent = '';
+        }, 2000);
+    } catch (err) {
+        console.error('Failed to copy:', err);
+        tooltip.textContent = 'Failed to copy';
+        button.classList.add('copied');
+        
+        setTimeout(() => {
+            button.classList.remove('copied');
+            tooltip.textContent = '';
+        }, 2000);
+    } finally {
+        document.body.removeChild(textarea);
+    }
+} 

Some files were not shown because too many files changed in this diff