<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Frontend | Nerdpress.org</title>
	<atom:link href="https://nerdpress.org/category/frontend-engineering/feed/" rel="self" type="application/rss+xml" />
	<link>https://nerdpress.org</link>
	<description>...dev, tech problems and solutions.</description>
	<lastBuildDate>Sat, 28 Feb 2026 14:46:50 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>A WordPress-like More Tag in Astro</title>
		<link>https://nerdpress.org/2026/02/28/a-wordpress-like-more-tag-in-astro/</link>
		
		<dc:creator><![CDATA[Ivo Bathke]]></dc:creator>
		<pubDate>Sat, 28 Feb 2026 14:46:49 +0000</pubDate>
				<category><![CDATA[Astro]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Wordpress]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=3470</guid>

					<description><![CDATA[<p>When migrating from WordPress to Astro, one encounters various challenges.One is handling the WordPress &#8220;More&#8221; tag, which originates from the More Element in the WordPress Block Editor. After converting the WordPress export to Markdown, you will find `&#60;!&#8211; more &#8211;>` tags in your content. These tags serve as delimiters in WordPress, allowing you to define &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2026/02/28/a-wordpress-like-more-tag-in-astro/" class="more-link">Continue reading<span class="screen-reader-text"> "A WordPress-like More Tag in Astro"</span></a></p>
The post <a href="https://nerdpress.org/2026/02/28/a-wordpress-like-more-tag-in-astro/">A WordPress-like More Tag in Astro</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>When migrating from WordPress to Astro, one encounters various challenges.<br />One is handling the WordPress &#8220;More&#8221; tag, which originates from the More Element in the WordPress Block Editor.</p>



<p>After converting the WordPress export to Markdown, you will find `&lt;!&#8211; more &#8211;>` tags in your content. These tags serve as delimiters in WordPress, allowing you to define where the excerpt ends on listing pages.</p>



<span id="more-3470"></span>



<h2 class="wp-block-heading"><strong>The Challenge</strong></h2>



<p>Astro does not provide a built-in mechanism to handle these tags. I also could not find a suitable plugin that would manage this functionality.</p>



<p>My first approach was to use a Remark plugin like <a href="https://www.npmjs.com/package/remark-excerpt" target="_blank" rel="noopener" title="">remark-excerpt</a>. However, this did not work as expected. Instead of adding an Excerpt property to the frontmatter or to the data object of the content collection, it simply replaced the Content with the Excerpt.</p>



<p>Writing a custom Remark plugin proved challenging as well. While extracting the excerpt markdown is straightforward, rendering it to HTML is not. Since Astro does not expose its renderer (yet*), you would need to create your own renderer or use Astro&#8217;s internal `astrojs/markdown-remark`. Both approaches are rather hacky and not really recommended.</p>



<p>* <em>There are ongoing discussions about making the renderer API public: <a href="https://github.com/withastro/roadmap/discussions/1094" target="_blank" rel="noopener" title="">Astro Roadmap Discussion #1094.</a></em></p>



<h2 class="wp-block-heading"><strong>The Solution</strong></h2>



<p>The current best way to handle the WordPress More Tag in Astro is to split the rendered HTML content directly.</p>



<p>On the list page where you want to display the excerpt, you can map over the entries, split the rendered HTML at the <code>&lt;!--more--></code> tag, and add the excerpt to the return object:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> previewPosts = <span class="hljs-keyword">await</span> <span class="hljs-built_in">Promise</span>.all(
	posts.map(<span class="hljs-keyword">async</span> (post) =&gt; {
		<span class="hljs-keyword">const</span> fullHtml = post.rendered?.html || <span class="hljs-string">''</span>;
		<span class="hljs-keyword">const</span> moreIndex = fullHtml.indexOf(<span class="hljs-string">'&lt;!--more--&gt;'</span>);
		<span class="hljs-keyword">const</span> excerptHtml = moreIndex !== <span class="hljs-number">-1</span> ? fullHtml.slice(<span class="hljs-number">0</span>, moreIndex) : fullHtml;
		<span class="hljs-keyword">const</span> hasMore = moreIndex !== <span class="hljs-number">-1</span>;
		<span class="hljs-keyword">return</span> { post, hasMore, excerptHtml };
	}),
);

{previewPosts.map(<span class="hljs-function">(<span class="hljs-params">{ post, hasMore, Content }</span>) =&gt;</span> (
	<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"preview-content"</span>&gt;</span>
		<span class="hljs-tag">&lt;<span class="hljs-name">Content</span> /&gt;</span>
	<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
	{hasMore &amp;&amp; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"read-more"</span>&gt;</span>Read more...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>}
))}</code></span></pre>


<p>Straightforward and effective :)</p>



<p></p>The post <a href="https://nerdpress.org/2026/02/28/a-wordpress-like-more-tag-in-astro/">A WordPress-like More Tag in Astro</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Dynamic OpenGraph Images in Astro</title>
		<link>https://nerdpress.org/2025/12/23/dynamic-opengraph-images-in-astro/</link>
		
		<dc:creator><![CDATA[Ivo Bathke]]></dc:creator>
		<pubDate>Tue, 23 Dec 2025 13:13:06 +0000</pubDate>
				<category><![CDATA[Astro]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[OpenGraph]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=3457</guid>

					<description><![CDATA[<p>If you&#8217;ve ever shared a link on social media, you know how critical OpenGraph (OG) images are. They&#8217;re the first thing people see &#8211; often before they even click.Static OG images are fine as a start, but what if you want custom images for every blog post or content collection item? For Astro there is &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2025/12/23/dynamic-opengraph-images-in-astro/" class="more-link">Continue reading<span class="screen-reader-text"> "Dynamic OpenGraph Images in Astro"</span></a></p>
The post <a href="https://nerdpress.org/2025/12/23/dynamic-opengraph-images-in-astro/">Dynamic OpenGraph Images in Astro</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>If you&#8217;ve ever shared a link on social media, you know how critical OpenGraph (OG) images are. They&#8217;re the first thing people see &#8211; often before they even click.<br />Static OG images are fine as a start, but what if you want <strong>custom images for every blog post or content collection item</strong>?</p>



<p>For Astro there is <a href="https://github.com/delucis/astro-og-canvas" target="_blank" rel="noopener" title="">astro-og-canvas</a>, a nice and useful Astro plugin that utilizes Canvas to create dynamic OG images.</p>



<p>In this post, I&#8217;ll walk you through how to generate dynamic OG images for your Astro site, inspired by <a href="https://aidankinzett.com/blog/astro-open-graph-image/" target="_blank" rel="noopener" title="">Aidan Kinzett&#8217;s excellent post</a>.<br />I&#8217;ll also share some odds and learned lessons.</p>



<span id="more-3457"></span>



<p><strong>Step 1: Set Up `astro-og-canvas`</strong></p>



<p>First, install the package:</p>



<p><code>npm install astro-og-canvas</code></p>



<p>Create a new file at <code>src/pages/og/[...routes].ts</code>.<br />This will dynamically generate images for your content.<br />Here&#8217;s how I set it up for my newsletter collection:</p>


<pre class="wp-block-code"><span><code class="hljs language-typescript"><span class="hljs-keyword">import</span> { OGImageRoute } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro-og-canvas"</span>;
<span class="hljs-keyword">import</span> { getCollection } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro:content"</span>;

<span class="hljs-comment">// Fetch all newsletter entries</span>
<span class="hljs-keyword">const</span> newsletters = <span class="hljs-keyword">await</span> getCollection(<span class="hljs-string">"newsletter"</span>);

<span class="hljs-comment">// Map newsletters to OG image configurations</span>
<span class="hljs-keyword">const</span> pages = {
  ...Object.fromEntries(
    newsletters.map(<span class="hljs-function">(<span class="hljs-params"><span class="hljs-params">newsletter</span></span>) =&gt;</span> &#91;
      newsletter.data.slug,
      {
        data: {
          title: newsletter.data.title,
          description: newsletter.data.newsletter.parts
            .map(<span class="hljs-function">(<span class="hljs-params"><span class="hljs-params">part</span></span>) =&gt;</span> <span class="hljs-string">`<span class="hljs-subst">${part.emoji.icon}</span> <span class="hljs-subst">${part.title}</span>`</span>)
            .join(<span class="hljs-string">" • "</span>),
        },
        slug: newsletter.data.slug,
      },
    ])
  ),
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { getStaticPaths, GET } = OGImageRoute({
  param: <span class="hljs-string">"route"</span>,
  pages,
  getImageOptions: <span class="hljs-keyword">async</span> (_, { data, slug }) =&gt; ({
    title: <span class="hljs-string">`Ivo's Ecotainment Newsletter: <span class="hljs-subst">${data.title}</span>`</span>,
    description: data.description,
    bgGradient: &#91;
      &#91;<span class="hljs-number">255</span>, <span class="hljs-number">221</span>, <span class="hljs-number">0</span>], <span class="hljs-comment">// Yellow (from logo)</span>
      &#91;<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>], <span class="hljs-comment">// White</span>
    ],
    logo: {
      path: <span class="hljs-string">"./public/Ivos-Ecotainment-Newsletter_Salamander.png"</span>,
      size: &#91;<span class="hljs-number">1080</span>],
    },
    border: {
      color: &#91;<span class="hljs-number">83</span>, <span class="hljs-number">174</span>, <span class="hljs-number">90</span>], <span class="hljs-comment">// Green accent</span>
      width: <span class="hljs-number">2</span>,
      side: <span class="hljs-string">"inline-start"</span>,
    },
    font: {
      title: {
        size: <span class="hljs-number">42</span>,
        weight: <span class="hljs-string">"Bold"</span>,
        families: &#91;<span class="hljs-string">"Noto Sans"</span>, <span class="hljs-string">"Noto Color Emoji"</span>],
        color: &#91;<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
      },
      description: {
        size: <span class="hljs-number">20</span>,
        weight: <span class="hljs-string">"Normal"</span>,
        families: &#91;<span class="hljs-string">"Noto Sans"</span>, <span class="hljs-string">"Noto Color Emoji"</span>],
        color: &#91;<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
        lineHeight: <span class="hljs-number">1.4</span>,
      },
    },
    fonts: &#91;
      <span class="hljs-string">"./public/fonts/Noto_Sans/NotoSans-VariableFont_wdth,wght.ttf"</span>,
      <span class="hljs-string">"./public/fonts/Noto_Color_Emoji/NotoColorEmoji-Regular.ttf"</span>,
    ],
    padding: <span class="hljs-number">50</span>,
  }),
});</code></span></pre>


<p><br /><strong>Some learned lessons:</strong><br />1. Logos: SVGs won&#8217;t work here. Use PNGs instead.<br />2. Fonts: Add font files, if you use fonts.<br />3. Emojis: If you use emojis in your content, include an emoji font (like &#8220;Noto Color Emoji&#8221;) to ensure they render correctly.</p>



<p><strong>Step 2: Integrate with astro-seo</strong></p>



<p>I use the <a href="https://github.com/jonasmerlin/astro-seo" target="_blank" rel="noopener" title="">astro-seo</a> component in my main Layout component to handle SEO metadata.</p>



<p>For the OG image I add a prop to be passed from the respective page:</p>


<pre class="wp-block-code"><span><code class="hljs language-typescript"><span class="hljs-keyword">const</span> { title, description, ogImage } = Astro.props;

&lt;SEO
  title={title}
  description={description}
  openGraph={{
    basic: {
      title,
      <span class="hljs-keyword">type</span>: <span class="hljs-string">"website"</span>,
      image: ogImage || <span class="hljs-string">`<span class="hljs-subst">${Astro.site}</span>Ivos-Ecotainment-Newsletter_big.png`</span>, <span class="hljs-comment">// Fallback</span>
    },
  }}
/&gt;</code></span></pre>


<p><strong>In Your Content Pages</strong>:<br />Construct the OG image path and pass it to your layout:</p>


<pre class="wp-block-code"><span><code class="hljs language-typescript"><span class="hljs-keyword">const</span> ogImage = <span class="hljs-string">`<span class="hljs-subst">${Astro.site?.href || <span class="hljs-string">""</span>}</span>og/<span class="hljs-subst">${entry.data.slug}</span>.png`</span>;

&lt;Layout title={entry.data.title} description={description} ogImage={ogImage}&gt;
  {<span class="hljs-comment">/* Post content */</span>}
&lt;<span class="hljs-regexp">/Layout&gt;</span></code></span></pre>


<p><strong>Astro Odds</strong>:</p>



<p>A bit odd is if your <code>astro.config.mjs</code> has <code>trailingSlash: "always"</code>, you&#8217;ll need to add a trailing slash to OG image URLs <strong>in development</strong>:<br /><code>http://localhost:4321/og/${entry.data.slug}.png/</code></p>



<p>In prod (no trailing slash needed) so you can just pass it as: <code>http://localhost:4321/og/${entry.data.slug}.png</code></p>



<p></p>



<p><strong>3. Testing OG Images</strong></p>



<p>As recommend in the Blog post of Aidan Kinzett: Use <a href="https://www.opengraph.xyz" target="_blank" rel="noopener" title="">opengraph.xyz</a>  to preview your OG images before sharing links.<br />Very good tool!</p>



<p>Here is how the OG image looks like with logo, title and description with emojis:</p>



<figure class="wp-block-image size-large"><a href="https://ivos-ecotainment-newsletter.info/archiv/pt58-party-parrot/"><img fetchpriority="high" decoding="async" width="1024" height="538" src="https://nerdpress.org/wp-content/uploads/2025/12/pt58-party-parrot-1024x538.png" alt="" class="wp-image-3462" srcset="https://nerdpress.org/wp-content/uploads/2025/12/pt58-party-parrot-1024x538.png 1024w, https://nerdpress.org/wp-content/uploads/2025/12/pt58-party-parrot-300x158.png 300w, https://nerdpress.org/wp-content/uploads/2025/12/pt58-party-parrot-768x403.png 768w, https://nerdpress.org/wp-content/uploads/2025/12/pt58-party-parrot.png 1200w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /></a></figure>



<p>Happy hacking!</p>



<p></p>The post <a href="https://nerdpress.org/2025/12/23/dynamic-opengraph-images-in-astro/">Dynamic OpenGraph Images in Astro</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>ObfuscateLink Web Component in Astro</title>
		<link>https://nerdpress.org/2025/02/07/obfuscatelink-web-component-in-astro/</link>
		
		<dc:creator><![CDATA[Ivo Bathke]]></dc:creator>
		<pubDate>Fri, 07 Feb 2025 09:36:02 +0000</pubDate>
				<category><![CDATA[Astro]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Web components]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=3393</guid>

					<description><![CDATA[<p>Using Web Components in Astro wasn&#8217;t as straightforward as expected. Here&#8217;s an example showing how to integrate the obfuscate-link web component into an Astro project.&#160; First, add the Obfuscate-Link web component to the project: Now register ObfuscateLink with customElements:&#160; This occurs in the Layout.astro component, making it available across all pages. The registration happens within &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2025/02/07/obfuscatelink-web-component-in-astro/" class="more-link">Continue reading<span class="screen-reader-text"> "ObfuscateLink Web Component in Astro"</span></a></p>
The post <a href="https://nerdpress.org/2025/02/07/obfuscatelink-web-component-in-astro/">ObfuscateLink Web Component in Astro</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Using Web Components in <a href="https://astro.build/" title="">Astro</a> wasn&#8217;t as straightforward as expected. Here&#8217;s an example showing how to integrate the <a href="https://github.com/ivoba/obfuscate-wc" title="">obfuscate-link</a> web component into an Astro project.&nbsp;</p>



<p>First, add the Obfuscate-Link web component to the project:</p>


<pre class="wp-block-code"><span><code class="hljs">npm install obfuscate-link-web-component</code></span></pre>


<span id="more-3393"></span>



<p>Now register ObfuscateLink with customElements:&nbsp;</p>


<pre class="wp-block-code"><span><code class="hljs language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
      <span class="hljs-keyword">import</span> { ObfuscateLink } <span class="hljs-keyword">from</span> <span class="hljs-string">'obfuscate-link-web-component'</span>;
      <span class="hljs-comment">// Only define the custom element if it hasn't been defined yet</span>
      <span class="hljs-keyword">if</span> (!customElements.get(<span class="hljs-string">'obfuscate-link'</span>)) {
        customElements.define(<span class="hljs-string">'obfuscate-link'</span>, ObfuscateLink);
      }
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span></code></span></pre>


<p>This occurs in the Layout.astro component, making it available across all pages. The registration happens within a script tag in the HTML to execute only on the client side, avoiding it execution while SSR rendering performed by Astro beforehand.</p>



<p>Next, create an Astro component that wraps the web-component and handles the obfuscation by encoding the passed prop.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">---
type BaseProps = {
  id?: string;
}
type EmailProps = BaseProps &amp; {
  <span class="hljs-attr">email</span>: string;
  tel?: never;
  sms?: never;
  facetime?: never;
  href?: never;
}
type TelProps = BaseProps &amp; {
  email?: never;
  tel: string;
  sms?: never;
  facetime?: never;
  href?: never;
}
type SmsProps = BaseProps &amp; {
  email?: never;
  tel?: never;
  sms: string;
  facetime?: never;
  href?: never;
}
type FacetimeProps = BaseProps &amp; {
  email?: never;
  tel?: never;
  sms?: never;
  facetime: string;
  href?: never;
}
type HrefProps = BaseProps &amp; {
  email?: never;
  tel?: never;
  sms?: never;
  facetime?: never;
  href: string;
}
<span class="hljs-keyword">export</span> type Props = EmailProps | TelProps | SmsProps | FacetimeProps | HrefProps;
<span class="hljs-keyword">const</span> props = Astro.props;
<span class="hljs-keyword">const</span> { id } = props;
<span class="hljs-comment">// Find the active prop (email, tel, sms, facetime, or href)</span>
<span class="hljs-keyword">const</span> activeProp = <span class="hljs-built_in">Object</span>.entries(props).find(<span class="hljs-function">(<span class="hljs-params">&#91;key, value]</span>) =&gt;</span> 
  key !== <span class="hljs-string">'id'</span> &amp;&amp; value !== <span class="hljs-literal">undefined</span>
);
<span class="hljs-keyword">let</span> attribute = <span class="hljs-string">''</span>;
<span class="hljs-keyword">let</span> value = <span class="hljs-string">''</span>;
<span class="hljs-keyword">if</span> (activeProp) {
  &#91;attribute, value] = activeProp;
  <span class="hljs-keyword">const</span> orgValue = value;
  value = Buffer.from(value).toString(<span class="hljs-string">'base64'</span>);
}
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">obfuscate-link</span>
  <span class="hljs-attr">id</span>=<span class="hljs-string">{id}</span>
  {<span class="hljs-attr">...</span>{&#91;<span class="hljs-attr">attribute</span>]<span class="hljs-attr">:</span> <span class="hljs-attr">value</span>}}
&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">obfuscate-link</span>&gt;</span></span></code></span></pre>


<p>Finally, you can utilize both the Astro component and the Web component throughout your Astro project.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">
---
<span class="hljs-keyword">import</span> ObfuscateLink <span class="hljs-keyword">from</span> <span class="hljs-string">'./ObfuscateLink.astro'</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
    Email: <span class="hljs-tag">&lt;<span class="hljs-name">ObfuscateLink</span> <span class="hljs-attr">email</span>=<span class="hljs-string">"info@example.com"</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span></code></span></pre>


<p>The complete code can be seen in this Gist: </p>



<p><a href="https://gist.github.com/ivoba/222d5a49ad4542392772195c5e5ad032" target="_blank" rel="noopener" title="">https://gist.github.com/ivoba/222d5a49ad4542392772195c5e5ad032</a></p>The post <a href="https://nerdpress.org/2025/02/07/obfuscatelink-web-component-in-astro/">ObfuscateLink Web Component in Astro</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Astro component for DarkMode Switcher for PicoCSS</title>
		<link>https://nerdpress.org/2024/01/07/astro-component-for-darkmode-switcher-for-picocss/</link>
		
		<dc:creator><![CDATA[Ivo Bathke]]></dc:creator>
		<pubDate>Sun, 07 Jan 2024 12:54:26 +0000</pubDate>
				<category><![CDATA[Astro]]></category>
		<category><![CDATA[PicoCSS]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=3289</guid>

					<description><![CDATA[<p>I am currently evaluating PicoCss V2 in Astro project. PicoCss is a CSS / SCSS framework I used for some of my projects because it is small and brings sufficient styling for most HTML Elements. It has integrated light and dark mode, but no theme switcher. So i was looking for one and found this &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2024/01/07/astro-component-for-darkmode-switcher-for-picocss/" class="more-link">Continue reading<span class="screen-reader-text"> "Astro component for DarkMode Switcher for PicoCSS"</span></a></p>
The post <a href="https://nerdpress.org/2024/01/07/astro-component-for-darkmode-switcher-for-picocss/">Astro component for DarkMode Switcher for PicoCSS</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>I am currently evaluating <a href="https://v2.picocss.com/" target="_blank" rel="noopener" title="">PicoCss V2</a> in <a href="https://astro.build/" target="_blank" rel="noopener" title="">Astro</a> project. PicoCss is a CSS / SCSS framework I used for some of my projects because it is small and brings sufficient styling for most HTML Elements. It has integrated light and dark mode, but no theme switcher. <br />So i was looking for one and found this one for Pico V1: <br /><a href="https://github.com/RWDevelopment/theme_switch" target="_blank" rel="noopener" title="">https://github.com/RWDevelopment/theme_switch</a></p>



<span id="more-3289"></span>



<p>I adjusted it to Pico V2 in a Astro component, ready to use in a Astro project with Pico V2 as CSS framework. <br />Since the component is just one file i just a made a gist: <a href="https://gist.github.com/ivoba/f3e0a8d7423faf318ce2217f5af9c510">https://gist.github.com/ivoba/f3e0a8d7423faf318ce2217f5af9c510</a></p>



<p>Here is how to use it, f.e. in your navigation:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">---
<span class="hljs-keyword">import</span> ThemeSwitcher <span class="hljs-keyword">from</span> <span class="hljs-string">"./ThemeSwitcher.astro"</span>;
---

...
  
&lt;li&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeSwitcher</span> /&gt;</span></span>
&lt;<span class="hljs-regexp">/li&gt;</span></code></span></pre>


<p><strong>Update:</strong><br />I added a persistence layer for localStorage to the Gist.<br />So the selected theme is remembered between pages.</p>The post <a href="https://nerdpress.org/2024/01/07/astro-component-for-darkmode-switcher-for-picocss/">Astro component for DarkMode Switcher for PicoCSS</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Obfuscate Web Component</title>
		<link>https://nerdpress.org/2023/12/08/obfuscate-web-component/</link>
		
		<dc:creator><![CDATA[Ivo Bathke]]></dc:creator>
		<pubDate>Fri, 08 Dec 2023 17:21:01 +0000</pubDate>
				<category><![CDATA[Astro]]></category>
		<category><![CDATA[Web components]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=3281</guid>

					<description><![CDATA[<p>Typically, when integrating emails into websites, I obfuscate the email address to prevent spam bots from collecting them. For React, there were already components that handled this task; however, without React, I couldn&#8217;t find a suitable solution. Therefore, I created a web component: obfuscate-wc that now provides an HTML element capable of obfuscating your email &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2023/12/08/obfuscate-web-component/" class="more-link">Continue reading<span class="screen-reader-text"> "Obfuscate Web Component"</span></a></p>
The post <a href="https://nerdpress.org/2023/12/08/obfuscate-web-component/">Obfuscate Web Component</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Typically, when integrating emails into websites, I obfuscate the email address to prevent spam bots from collecting them. For React, there were already components that handled this task; however, without React, I couldn&#8217;t find a suitable solution.</p>



<p>Therefore, I created a web component: <a href="https://github.com/ivoba/obfuscate-wc" target="_blank" rel="noopener" title="">obfuscate-wc</a> that now provides an HTML element capable of obfuscating your email (and some other contact data).</p>


<pre class="wp-block-code"><span><code class="hljs language-xml"> <span class="hljs-tag">&lt;<span class="hljs-name">obfuscate-link</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"obfuscate"</span> <span class="hljs-attr">email</span>=<span class="hljs-string">"aXZvQGxvY2FsLmRldg=="</span>&gt;</span>custom link<span class="hljs-tag">&lt;/<span class="hljs-name">obfuscate-link</span>&gt;</span></code></span></pre>


<span id="more-3281"></span>



<p>The component accepts an encoded email address, rendering it human-readable after events that typically align with human browsing behavior. <br />Custom decoders can be configured, with the default set to base64. <br />While sophisticated spam crawlers may still manage to decode the email, the likelihood decreases as you customize your encoder/decoder. It&#8217;s worth noting that the decoder could also be crawled, but the assumption is that this presents too much effort for the crawlers.</p>



<p>Using the web component itself is already blocking spammer that just look for mailto links.</p>



<p>How did I get there?</p>



<p>When using React I took this React component: <a href="https://github.com/coston/react-obfuscate" target="_blank" rel="noopener" title="">https://github.com/coston/react-obfuscate</a></p>



<p>In a new project, I began using <a href="https://astro.build/" target="_blank" rel="noopener" title="">Astro</a>, and React became unnecessary. However, I found myself missing the obfuscation component. Consequently, I chose to create a web component with similar functionality. This endeavor also served as a valuable exploration into web components. Web components, native to the browser, enable you to define your own HTML tags with specific functionality within the component.</p>



<p>Since the API of the web components is not the nicest, let&#8217;s say.<br />I took <a href="https://stenciljs.com/" target="_blank" rel="noopener" title="">StencilJs</a> which is a framework for Web Component development.<br />It also comes with nice tooling like Typescript support, tests and builds helpers.</p>



<p>I crafted it with Stencil, learned the process of building the component&#8211;admittedly, this was a bit cumbersome&#8211;but now it&#8217;s ready for use in any web application.</p>The post <a href="https://nerdpress.org/2023/12/08/obfuscate-web-component/">Obfuscate Web Component</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Migrating from gulp to esbuild</title>
		<link>https://nerdpress.org/2021/07/23/migrating-from-gulp-to-esbuild/</link>
		
		<dc:creator><![CDATA[Ivo Bathke]]></dc:creator>
		<pubDate>Fri, 23 Jul 2021 15:06:46 +0000</pubDate>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Frontend]]></category>
		<category><![CDATA[JS]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[esbuild]]></category>
		<category><![CDATA[gulp]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[sass]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=3066</guid>

					<description><![CDATA[<p>Esbuild is the new cool kid in the bundler world.It is super fast since its written in Go and comes with a lot of builtin features for modern frontend development. So i wanted to try it myself and migrated a former gulp build to esbuild. But as it showed the gulp build was not so &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2021/07/23/migrating-from-gulp-to-esbuild/" class="more-link">Continue reading<span class="screen-reader-text"> "Migrating from gulp to esbuild"</span></a></p>
The post <a href="https://nerdpress.org/2021/07/23/migrating-from-gulp-to-esbuild/">Migrating from gulp to esbuild</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p><a href="https://esbuild.github.io/" target="_blank" rel="noreferrer noopener">Esbuild</a> is the new cool kid in the bundler world.<br />It is super fast since its written in Go and comes with a lot of builtin features for modern frontend development.</p>



<p>So i wanted to try it myself and migrated a former <a href="https://gulpjs.com/" title="https://gulpjs.com/" target="_blank" rel="noreferrer noopener">gulp</a> build to esbuild.</p>



<p>But as it showed the gulp build was not so modern, as it was just Sass and Javascript minification. No ES6, No React, no JSX with inline styles.</p>



<p>So Esbuild was not working out of the box but needed some extra config and the <a href="https://www.npmjs.com/package/esbuild-plugin-sass" target="_blank" rel="noreferrer noopener">Sass plugin</a>.</p>



<p><code>npm i -d esbuild esbuild-plugin-sass</code></p>



<p>Also I had to rewrite the Javascript to use ES6 modules, but this was fortunatly easy.</p>



<span id="more-3066"></span>



<p>When using a plugin we need to create our own build file and configure esbuild to use the Sass plugin.<br />esbuild.js:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
const esbuild = require(&#039;esbuild&#039;);
const sassPlugin = require(&#039;esbuild-plugin-sass&#039;);

esbuild.build({
  entryPoints: &#x5B;&quot;main.js&quot;],
  bundle: true,
  minify: true,
  format: &#039;iife&#039;,
  platform: &#039;browser&#039;,
  outfile:&quot;main.min.js&quot;,
  plugins: &#x5B;sassPlugin()]
}).catch((err) =&gt; {
  console.log(err)
})
</pre></div>


<p>Ok, but where are the Sass files now?<br />With ES6 you can import styles and then esbuild &amp; the sassPlugin can follow this path from the entrypoint file and create the CSS file from the source Sass file.</p>



<p>So in main.js import the styles:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
import $ from &#039;jquery&#039;
import &#039;./style.scss&#039;
...
</pre></div>


<p>Now you can call the esbuild.js file:</p>



<p><code>node ./esbuild.js</code></p>



<p><em>(Yeah no file watchers here, just manual trigger ;))</em></p>



<p>This will bundle the javascript to main.min.js and also create a main.min.css file.</p>



<p>Then include this in your HTML</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; title: ; notranslate">
&lt;link rel=&quot;stylesheet&quot; href=&quot;/main.min.css&quot;&gt; 
&lt;script src=&quot;/main.min.js&quot;&gt;&lt;/script&gt;
</pre></div>


<p>and you are done. :)</p>The post <a href="https://nerdpress.org/2021/07/23/migrating-from-gulp-to-esbuild/">Migrating from gulp to esbuild</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>mashcloud.net &#8211; mashup soundcloud audio tracks</title>
		<link>https://nerdpress.org/2013/01/24/mashcloud-net-mashup-soundcloud-audio-tracks/</link>
		
		<dc:creator><![CDATA[Max Girkens]]></dc:creator>
		<pubDate>Thu, 24 Jan 2013 20:08:28 +0000</pubDate>
				<category><![CDATA[API]]></category>
		<category><![CDATA[Express]]></category>
		<category><![CDATA[Frontend]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[JS]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[socket.io]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[sockets]]></category>
		<category><![CDATA[soundcloud]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=2359</guid>

					<description><![CDATA[<p>mashcloud.net is an experiment on collaborative realtime audio editing and music creation. I did the project within the frame of  my BA thesis in audio production last year. As I moved the code to github this week, I wanted to give a quick overview of the project and its technical underlyings, just in case someone might &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2013/01/24/mashcloud-net-mashup-soundcloud-audio-tracks/" class="more-link">Continue reading<span class="screen-reader-text"> "mashcloud.net &#8211; mashup soundcloud audio tracks"</span></a></p>
The post <a href="https://nerdpress.org/2013/01/24/mashcloud-net-mashup-soundcloud-audio-tracks/">mashcloud.net – mashup soundcloud audio tracks</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p><a href="http://mashcloud.net/">mashcloud.net</a> is an experiment on collaborative realtime audio editing and music creation. <br />I did the project within the frame of  my BA thesis in audio production last year.</p>
<p>As I moved the code to <a href="https://github.com/gherkins/mashcloud">github</a> this week, I wanted to give a quick overview of the project and its technical underlyings, just in case someone might be interested :)</p>
<p><span id="more-2359"></span>As the title of this post might already suggest, its about selecting and layering loops from audiofiles hosted on <a href="http://soundcloud.com">soundcloud.com</a> and thereby creating new music.</p>
<p><a href="https://nerdpress.org/2013/01/24/mashcloud-net-mashup-soundcloud-audio-tracks/bildschirmfoto-2013-01-24-um-20-46-08/" rel="attachment wp-att-2363"><img decoding="async" class="alignnone size-medium wp-image-2363" alt="Bildschirmfoto 2013-01-24 um 20.46.08" src="https://nerdpress.org/wp-content/uploads/2013/01/Bildschirmfoto-2013-01-24-um-20.46.08-300x174.png" width="300" height="174" srcset="https://nerdpress.org/wp-content/uploads/2013/01/Bildschirmfoto-2013-01-24-um-20.46.08-300x174.png 300w, https://nerdpress.org/wp-content/uploads/2013/01/Bildschirmfoto-2013-01-24-um-20.46.08-1024x593.png 1024w, https://nerdpress.org/wp-content/uploads/2013/01/Bildschirmfoto-2013-01-24-um-20.46.08.png 1050w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>Those collections of layered loops are called a session. Sessions can be created anonymously by everyone and are auto-saved on every action. By distributing the URL of a session other users can join and every action is synced between all users in realtime. <br />(complete mayhem, indeed :)</p>
<p>The application is built with HTML5 and JS w/ <a href="http://jquery.com/">jQuery</a> using the <a href="http://developers.soundcloud.com/docs/api/guide">soundcloud API</a> on the client side and runs on <a href="http://nodejs.org/">node.js</a> &amp; <a href="http://www.mongodb.org/">mongoDB</a> with <a href="http://expressjs.com/">express</a>, <a href="http://socket.io/">socket.io</a> and <a href="http://mongoosejs.com/">mongoose</a> on the server side.</p>
<p>I basically started the project to find out if you could play multiple loops asynchronous and synced with low latency using the <a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html">Web Audio API</a> while collaboratively working together with multiple users in realtime. </p>
<p>As that turned out to be not only possible but performed real nicely, the experiment then developed in somewhat of an application and finally got a name and a face.</p>
<p>There&#8217;s a whole lot of things i&#8217;d like to implement / refactor and do when i get some time on my hands, as</p>
<p>&#8211; adding a &#8220;record&#8221; feature to record, save and export created sessions as audiofiles</p>
<p>&#8211; rewriting the client side with <a href="http://backbonejs.org/">backbone.js</a> (as things got a bit messy &#8230;)</p>
<p>&#8211; adding some audio effects to the tracks</p>
<p>&#8211; write some tests</p>
<p>I&#8217;d appreciate any form of contribution as much as any questions or feedback on the project :)</p>
<p>Feel free to check out the live version at <a href="http://mashcloud.net/"> http://mashcloud.net/</a> or the sources at <a href="https://github.com/gherkins/mashcloud">https://github.com/gherkins/mashcloud</a></p>The post <a href="https://nerdpress.org/2013/01/24/mashcloud-net-mashup-soundcloud-audio-tracks/">mashcloud.net – mashup soundcloud audio tracks</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>[Symfony 2][Assetic] Sass, CompassFilter + Foundation Responsive Front-end Framework</title>
		<link>https://nerdpress.org/2012/10/26/symfony-2assetic-sass-compassfilter-foundation-responsive-front-end-framework/</link>
					<comments>https://nerdpress.org/2012/10/26/symfony-2assetic-sass-compassfilter-foundation-responsive-front-end-framework/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 26 Oct 2012 15:32:56 +0000</pubDate>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Frontend]]></category>
		<category><![CDATA[JS]]></category>
		<category><![CDATA[Silex]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Tools]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=2323</guid>

					<description><![CDATA[<p>Did you ever wonder how to enable 3rd party plugins (or so called &#8220;frameworks&#8220;) within the great compass toolset managed by assetic in your edgy symfony 2.1 project? (If there is more extensive documentation available concerning assetic + CompassFilter, please stop reading on and let me know!) If you take a look at the filter &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2012/10/26/symfony-2assetic-sass-compassfilter-foundation-responsive-front-end-framework/" class="more-link">Continue reading<span class="screen-reader-text"> "[Symfony 2][Assetic] Sass, CompassFilter + Foundation Responsive Front-end Framework"</span></a></p>
The post <a href="https://nerdpress.org/2012/10/26/symfony-2assetic-sass-compassfilter-foundation-responsive-front-end-framework/">[Symfony 2][Assetic] Sass, CompassFilter + Foundation Responsive Front-end Framework</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Did you ever wonder how to enable 3rd <a href="http://compass-style.org/frameworks/">party</a> plugins (or so called &#8220;<a href="http://compass-style.org/frameworks/">frameworks</a>&#8220;) within the great <a href="http://compass-style.org/">compass toolset</a> managed by <a href="https://github.com/kriswallsmith/assetic">assetic</a> in your edgy <a href="http://symfony.com/">symfony 2.1</a> project?</p>
<p>(If there is more extensive documentation available concerning assetic + CompassFilter, please stop reading on and let me know!)</p>
<p>If you take a look at the filter class itself (it is CompassFilter in the generic Assetic\Filter namespace), you should recognise several option values that you can use in your application wide config.yml file.</p>
<p>But first you have to install the framework plugin following these <a href="http://foundation.zurb.com/docs/gem-install.php">instructions</a>.</p>
<p><span id="more-2323"></span></p>
<p>After adding the framework plugin by ruby&#8217;s own package manager &#8220;gem&#8221; (hopefully replaced by composer in the near future ;-)) by typing something like</p>
<pre class="brush: bash; title: ; notranslate">$ gem install zurb-foundation</pre>
<p>the only thing remaining to do is to load the framework plugin by assetic. To do so, put the folloging lines to your config.yml assetic section (as you would do it when using the compass command line interface, refer to the output of</p>
<pre class="brush: bash; title: ; notranslate">$ compass help compile</pre>
<p>.)</p>
<p>The yaml file should look like this:</p>
<pre class="brush: python; title: ; notranslate">
assetic:
    read_from: %kernel.root_dir%/web
    debug: %kernel.debug%
    use_controller: %kernel.debug%
    filters:
        compass:
            plugins: &#x5B;'zurb-foundation'] 
            # load foundation                                     
            # framework as you would do by typing
            # $ compass compile --require 
            # zurb-foundation &#x5B;...]
            # &#x5B; ... ]
</pre>
<p>Now you should be able to import the foundation library files by using the @import statement in your *.sass/*.scss files:</p>
<pre class="brush: css; title: ; notranslate">
@import &quot;foundation&quot;;
</pre>
<p>Have fun!</p>The post <a href="https://nerdpress.org/2012/10/26/symfony-2assetic-sass-compassfilter-foundation-responsive-front-end-framework/">[Symfony 2][Assetic] Sass, CompassFilter + Foundation Responsive Front-end Framework</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
					<wfw:commentRss>https://nerdpress.org/2012/10/26/symfony-2assetic-sass-compassfilter-foundation-responsive-front-end-framework/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Tilt &#8211; 3D DOM visualization</title>
		<link>https://nerdpress.org/2011/09/23/tilt-3d-dom-visualization/</link>
		
		<dc:creator><![CDATA[Max Girkens]]></dc:creator>
		<pubDate>Fri, 23 Sep 2011 06:00:57 +0000</pubDate>
				<category><![CDATA[Frontend]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[3D]]></category>
		<category><![CDATA[Addon]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[tilt]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=1722</guid>

					<description><![CDATA[<p>someone just +1&#8217;d this nice addon for firefox: (thanks, conrad :) Tilt visualizes the DOM in 3D and is a lot faster than i expected. Although it&#8217;s flagged experimental it&#8217;s easily installed and works like a charm on my macbook with Firefox 6. Definetly makes you think twice about your markup nesting level ;)</p>
The post <a href="https://nerdpress.org/2011/09/23/tilt-3d-dom-visualization/">Tilt – 3D DOM visualization</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>someone just +1&#8217;d this nice <a title="TILT firefox addon" href="https://addons.mozilla.org/de/firefox/addon/tilt/">addon</a> for firefox:<br />
(thanks, conrad :)</p>
<p><a href="https://nerdpress.org/wp-content/uploads/2011/09/tilt_firefox_3d_dom_addon1.png"><img decoding="async" class="alignnone size-medium wp-image-1725" title="tilt_firefox_3d_dom_addon" src="https://nerdpress.org/wp-content/uploads/2011/09/tilt_firefox_3d_dom_addon1-300x160.png" alt="TILT - firefox addon visualizes 3D" width="300" height="160" srcset="https://nerdpress.org/wp-content/uploads/2011/09/tilt_firefox_3d_dom_addon1-300x160.png 300w, https://nerdpress.org/wp-content/uploads/2011/09/tilt_firefox_3d_dom_addon1.png 960w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p><a href="https://addons.mozilla.org/de/firefox/addon/tilt/">Tilt</a> visualizes the DOM in 3D and is a lot faster than i expected.<br />
<span id="more-1722"></span><br />
Although it&#8217;s flagged experimental it&#8217;s easily installed and works like a charm on my macbook with Firefox 6.</p>
<p>Definetly makes you think twice about your markup nesting level ;)</p>
<p><object style="height: 390px; width: 640px;" width="640" height="360" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://www.youtube.com/v/dW2eAbr5FBw?version=3" /><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><embed style="height: 390px; width: 640px;" width="640" height="360" type="application/x-shockwave-flash" src="https://www.youtube.com/v/dW2eAbr5FBw?version=3" allowFullScreen="true" allowScriptAccess="always" allowfullscreen="true" allowscriptaccess="always" /></object></p>The post <a href="https://nerdpress.org/2011/09/23/tilt-3d-dom-visualization/">Tilt – 3D DOM visualization</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>[Symfony 2] AsseticBundle, Less CSS &#038; YUI Compressor unter OSX installieren</title>
		<link>https://nerdpress.org/2011/08/25/symfony-2-asseticbundle-less-css-yui-compressor-unter-osx-installieren/</link>
					<comments>https://nerdpress.org/2011/08/25/symfony-2-asseticbundle-less-css-yui-compressor-unter-osx-installieren/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Thu, 25 Aug 2011 16:55:02 +0000</pubDate>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[JS]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Assetic]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[less]]></category>
		<category><![CDATA[symfony 2]]></category>
		<category><![CDATA[Twig]]></category>
		<category><![CDATA[yui-compressor]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=1600</guid>

					<description><![CDATA[<p>Less CSS und YUI-Compressor mit Assetic unter OSX installieren und innerhalb Symfony 2 konfigurieren.</p>
The post <a href="https://nerdpress.org/2011/08/25/symfony-2-asseticbundle-less-css-yui-compressor-unter-osx-installieren/">[Symfony 2] AsseticBundle, Less CSS & YUI Compressor unter OSX installieren</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Das AsseticBundle ist ein Wrapper um <a href="https://github.com/kriswallsmith/assetic">Assetic</a>, ein geniales Tool, um statische Assets für Webprojekte zu verwalten. AsseticBundle ist extrem einfach zu verwenden, einfach die entsprechende Filter-Chain via yaml konfigurieren, um mehr muss man sich nicht kümmern. Natürlich allerdings müssen die zugrundeliegenden Abhängigkeiten im Vorfeld installiert sein. In unserem Falle benötigen wir den <a href="http://developer.yahoo.com/yui/compressor/">Yui-Compressor</a> als jar-File und <a href="http://lesscss.org/">Less CSS</a>. Less ist ein <a href="http://nodejs.org/">node.js</a> Modul, was bedingt, dass wir zuvor node.js installieren müssen.<br />
<span id="more-1600"></span></p>
<p>Also node.js via macports holen:</p>
<pre class="brush: bash; title: ; notranslate">
$ sudo port install nodejs
</pre>
<p>Und den node.js-eigenen Package-Manager:</p>
<pre class="brush: bash; title: ; notranslate">
$ sudo port install npm
</pre>
<p>Mit diesem installieren wir als nächsts less, und zwar &#8220;global&#8221; (via -g)-Flag (&#8220;global&#8221; bedeutet, dass das Modul unter $nodejs_lib_path/../node_modules abgelegt wird, ansonsten wird es im aktuellen Arbeitsverzeichnis unter ./node_modules installiert):</p>
<pre class="brush: bash; title: ; notranslate">
$ sudo npm install -g less
</pre>
<p>Damit haben wir alles, um unsere less CSS Stylesheets kompilieren zu können.</p>
<p>Als nächstes holen wir uns den Yui-Kompressor, diesen habe ich mir einfach aus dem Netz gezogen und unter app/java/yuicompressor-2.4.6.jar abgelegt (Die Binary findet ihr unter <a href="http://developer.yahoo.com/yui/compressor/">http://developer.yahoo.com/yui/compressor/</a>).</p>
<p>Nun die Konfiguration:</p>
<p>app/config.yml:</p>
<pre class="brush: python; title: ; notranslate">
# Assetic Configuration
assetic:
    debug:          %kernel.debug%
    use_controller: false
    filters:
        cssrewrite: ~
        less:
          node: /opt/local/bin/node
          node_paths: &#x5B;/opt/local/lib/node, /opt/local/lib/node_modules]
        yui_css:
          jar: %kernel.root_dir%/java/yuicompressor-2.4.6.jar
</pre>
<p>Zu beachten sind die &#8220;node_paths&#8221;. Der node.js-Modulpfad muss explizit angegeben werden, sonst kann node.js die require()-Statements nicht auflösen (das sind sozusagen die node.js-&#8220;Classpaths&#8221;). /opt/local/lib/node zeigt auf Core-Module, in /opt/local/lib/node_modules liegt unser less.</p>
<p>Um den Yui-Kompressor zu aktivieren, reicht der simple Pfad zur .jar-Datei.</p>
<p>Nun müssen wir nur noch unser Twig-Layout anpassen:</p>
<p>src/Nerdpress/DemoBundle/Resources/views/layout.html.twig:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
        {% stylesheets
                '@NerdpressDemoBundle/Resources/public/css/main.css'
                '@NerdpressDemoBundle/Resources/public/css/layout.css'
        	filter='less,?yui_css'
                combine=true
        %}
          &lt;link rel=&quot;stylesheet&quot; href=&quot;{{ asset_url }}&quot; type=&quot;text/css&quot; media=&quot;all&quot; /&gt;
        {% endstylesheets %}
</pre>
<p>Das &#8220;?&#8221; vor dem Filter &#8220;yui_css&#8221; bedingt, dass die CSS-Compression nur angeschaltet wird, wenn der Debug-Parameter auf false steht. &#8220;Combine&#8221; bedeutet, dass alle CSS-Dateien in einer einzigen, großen Datei zusammengefügt werden, und &#8220;less&#8221; bedeutet letztlich, dass alle CSS-Dateien mittels less CSS precompiled werden.</p>
<p>That´s it. Die Seite im Browser öffnen und das Ergebnis bewundern. Viel Spaß! Symfony ist schon was feines&#8230;</p>The post <a href="https://nerdpress.org/2011/08/25/symfony-2-asseticbundle-less-css-yui-compressor-unter-osx-installieren/">[Symfony 2] AsseticBundle, Less CSS & YUI Compressor unter OSX installieren</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
					<wfw:commentRss>https://nerdpress.org/2011/08/25/symfony-2-asseticbundle-less-css-yui-compressor-unter-osx-installieren/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
