Joining PDFs with Linux command line

There are several ways to merge two (or more) PDF files to a single file using the Linux command line.

If you're looking for graphical tools to edit or annotate a PDF, we have a separate card for that.

PDFtk (recommended)

PDFtk is a great toolkit for manipulating PDF documents. You may need to install it first (sudo apt install pdftk).
Merging multiple files works like this:

pdftk one.pdf two.pdf cat output out.pdf

Unlike pdfjam, PDFtk should not mess with page sizes but simply joins pages as they are.

...

Controlling how your website appears on social media feeds

When a user shares your content, a snippet with title, image, link and description appears in her timeline. By default social networks will use the window title, the first image, the current URL and some random text snippet for this purpose. This is often not what you want.

Luckily Facebook, Twitter, etc. lets you control how your content appears in the activity streams. They even have agreed on a common format to do this: OpenGraph <meta> tags that go into your HTML's <head>:

<meta property="og:url" content="http://start.m...

Webpack(er): A primer

webpack is a very powerful asset bundler written in node.js to bundle (ES6) JavaScript modules, stylesheets, images, and other assets for consumption in browsers.

Webpacker is a wrapper around webpack that handles integration with Rails.

This is a short introduction.

Installation

If you haven't already, you need to install node.js and Yarn.

Then, put

gem 'webpacker', '~> 4.x' # check if 4.x is still cu...

Adding Jasmine JavaScript specs to a Webpack(er) project

The goal is to get Jasmine specs running in a Rails project using Webpacker, with the browser based test runner. Should be easily adaptable to a pure Webpack setup.

Image

Step 1: Install Jasmine

yarn add jasmine-core

Step 2: Add two separate packs

Since we do not want to mix Jasmine into our regular Javascript, we will create two additional packs. The first only contains Jasmine and the test runner. The second will contain our normal application code and the specs themselves.

We cannot...

Webpack: Automatically generating an icon font from .svg files

Over the years we have tried several solution to have vector icons in our applications. There are many ways to achieve this, from SVGs inlined into the HTML, SVGs inlined in CSS, JavaScript-based solutions, to icon fonts.

Out of all these options, the tried and true icon font seems to have the most advantages, since

  • icon fonts are supported everywhere
  • they perform well and require no JavaScript at all
  • their icons align nicely with text
  • their icons automatically inherit color and size of the surrounding text

The big issue used to b...

SameSite cookies

TL;DR Most web applications do not require action on this. SameSite=None (old browser default) will continue to work, and SameSite=Lax (new Chrome default, gradually rolled out) is an even better default for cookies. Set SameSite=Strict only for extra security in special cases (see below). If your application is rendered in an iframe (e.g. a video player or some news stream), you need to configure its relevant cookies as SameSite=None.


The SameSite cookie attribute targets **c...

Self-expiring URLs with Apache

When delivering non-public uploaded files (images, documents etc), one has to decide whether and how to do authorization. The usual approaches are:

  • Using send_file with a regular controller. This is secure, but potentially slow, especially for large collections of images.
  • Using unguessable URLs. This is fast (because Apache can deliver assets without going through Rails), but less secure.

When going with the "unguessable URL" approach, it is possible to somewhat increase security by using expiring URLs. The idea is to encode the expi...

How to test Autoprefixer and CSSnext in PostCSS

PostCSS is a tool for transforming styles with JS plugins. In Webpacker you can configure the plugins and their settings via the postcss.config.js file. Make sure that postcss-loader is part of your package.json.

module.exports = {
  plugins: [
    require('postcss-import'),
    require('postcss-flexbugs-fixes'),
    require('postcss-preset-env')({
      autoprefixer: {
        flexbox: 'no-2009'
      },
      stage: 3
    })
  ]
}

Note: Stage 3 means you can use all CSS features that ar...

HTML emails with inline stylesheets and webpacker

Many mail clients do not support external style sheets. Some even require all styling inline, which means you'll have to do your styling inline. For Rails applications, you can use Roadie or premailer, which lets you keep your well-structured CSS files and do the inlining for you.

See Designing HTML email

Since Roadie is now in passive maintenance mode, we go with premailer:

Include premailer in your Gemfile:

gem 'premailer-ra...

Bootstrap 4 skin for the Rome datepicker

Here is how to make Rome datepicker look like the rest of your Bootstrap 4 application.

Rome comes with very little basic styling. While we could redefine its classes, we can configure the classes Rome applies to its elements to make it look like this:

Example Image

Since Bootstrap 4 comes with several helpful utility classes, and requires fewer markup/containers, we can achieve Bootstrap 4 experience by applying a few classes via the styles setting.

You still need to include `ro...

Carrierwave: always limit images to a reasonable size

Today's cameras create huge images, some beyond 50MB. Unless you need to offer this large files, you should always shrink uploaded files to a reasonable resolution.

class ImageUploader < CarrierWave::Uploader::Base
  
  process resize_to_limit: [3000, 3000]
  
  # ...

end

Carrierwave processing facts

  1. Class-level process definitions are only applied to the original file
  2. Versions are generated based on the processed original file
  3. Callbacks (before/after) are applied to original file and each version by itself
  4. Under the hood, a version is an instance of the uploader class that has no versions
  5. Version uploader and original uploader can be distinguished by checking #version_name: version uploaders return the version name, whereas the original uploader instance returns nil
  6. Version instances do not have a re...

Carrierwave: Built-in resize methods

Carrierwave includes some handy helper methods you can use to resize your images. Here is a quick summary of them, if you need more details read the docs. You can also use all command line options from RMagick directly if these helpers are not good enough for you.

resize_to_limit(width, height)
resize_to_fit(width, height)
resize_to_fi...

JavaScript without jQuery (presentation from 2019-01-21)

Summary

  • We want to move away from jQuery in future projects
  • Motivations are performance, bundle size and general trends for the web platform.
  • The native DOM API is much nicer than it used to be, and we can polyfill the missing pieces
  • Unpoly 0.60.0 works with or without jQuery

Is jQuery slow?

From: Sven
To: unpoly@googlegroups.com
Subject: performance on smartphones and tablets

Hello

I just used your framework in one project and must say,
I am really pleased with it -- but only on a desktop computer.

Have you benchm...

Upgrading Ruby from 1.8.7 to 2.3.5

Suggested Workflow

Set the ruby version in .ruby-version to 2.3.5, then perform these steps one by one, fixing errors as they occur:

  1. Update gems as listed below, and bundle
  2. Boot a Rails console - see below for a list of changes you will probably need
  3. Run Specs with --backtrace option
  4. Run Cucumber features (with Geordi's --debug option)
  5. When all tests are green, look through your Gemfile and remove as many version constraints as possible.
  6. Boot the application in different environements to spot further issues, e...

How to access before/after pseudo element styles with JavaScript

Accessing pseudo elements via JavaScript or jQuery is often painful/impossible. However, accessing their styles is fairly simple.

Using getComputedStyle

First, find the element in question.

let element = document.querySelector('.my-element') // or $('.my-element').get(0) when using jQuery

Next, use JavaScript's getComputedStyle. It takes an optional 2nd argument to filter for pseudo elements.

let style = window.getComputedStyle(element, '::before')
let color = style.getPropertyValue('background-color...

Fixing "identify: not authorized"

Ubuntu has decided to disable PDF processing because ImageMagick and the underlying Ghostscript had several security issues.

When your Ghostscript is up to date (and receiving updates regularly), you can safely reactivate PDF processing on your computer like this:

  1. Open /etc/ImageMagick-6/policy.xml
    • For older versions of Ubuntu (or possibly ImageMagick), the path is /etc/ImageMagick/policy.xml
  2. Remove/Comment lines after <!-- disable ghostscript format types -->

If you need it enabled for a...

An incomplete guide to migrate a Rails application from paperclip to carrierwave

In this example we assume that not only the storage gem changes but also the file structure on disc.

A general approach

Part A: Create a commit which includes a script that allows you to copy the existing file to the new file structure.

Part B: Create a commit which removes all paperclip logic and replace it with the same code you used in the first commit

Part A

Here are some implementation details you might want to reuse:

  • Use the existing models to read the files from
  • Use your own carrierwave models to write t...

Introduction to Google Tag Manager (for web developers who know Google Analytics)

As a web developer, you know Google Analytics (GA). Probably you've dropped the GA snippet into more than one website, maybe you've even used its Javascript API to implement tracking at the event level.

Google Tag Manager (GTM) is a related tool, but on a higher level and thus with much more power. GTM is not a replacement for GA. Rather, it can make GA configurable without changing anything in the application's code base (and much more beyond, see below).

Only prefer GTM if the customer requests it, or if he is updating his tracking r...

Optimizing images for web

For webpages to load fast it's recommended to optimize images. Ideally an image's file size should be as small as possible while still being of decent quality. This card demonstrates two command line tools for image optimization

Use identify to fetch information about pictures. convert can change size/quality and strip meta information. Both commands are supplied by ImageMagick.

$ identify in.jpg
in.jpg JPEG 294x440 294x440+0+0 8-bit sRGB 92.8KB 0.000u 0:00.000
$ convert in.jpg -resize x220 -strip -set profile sRGB2014.icc -qua...