Google Search Completes Rollout of Link Spam Update

Google announced today that it has completed its rollout of the link spam update, which was started a month ago. In an effort to combat sites using spammy links to manipulate rankings, the search engine has developed more effective ways to identify and nullify link spam across multiple languages. The update took a couple weeks longer than anticipated but the algorithmic changes that re-assess the ranking of improperly qualified links has now been fully rolled out.

Commercial linking can be differentiated from link spam by specifying the appropriate rel attribute. For example, affiliate links must be identified to the search engine by  rel=”sponsored” in order to not trigger any negative effects from the most recent update. Website owners and content creators should be aware of the search engine’s requirements when publishing affiliate links or sponsored/guest posts. While it is appropriate and ethical to disclose commercial links in the content of the post, this is no longer sufficient for Google.

A post on the Google Search Central blog warns that this update carries a more strict response for sites that do not properly qualify commercial links:

When we detect sites engaging in either publishing or acquiring links with excessive sponsored and guest posting without proper link tags, algorithmic and manual actions may be applied, similar to affiliate links.

WordPress users who rely on plugins to manage sponsored and affiliate links will want to check to ensure they support the proper tagging for commercial links. Pretty Links, a link management and tracking plugin used by more than 300,000 WordPress sites, added support for the sponsored rel tag in version 3.1.0, along with sponsored toggle support in the block and TinyMCE editors. ThirstyAffiliates, another popular plugin active on more than 40,00 installs, has a global setting for adding rel attribute tags to links, which can also be adjusted on a per-link basis.

The are many other affiliate link management, tracking, and cloaking plugins out there that may not have been updated with settings for easily designating relattributes in links. Those who do not want to have negative effects from the link spam update may need the ability to bulk update their links to comply. If you rely on a link management plugin, it’s a good idea to check the plugin’s settings, and alternatively the plugin’s changelog, to see what features are supported.

Why Did You Start Using WordPress?

Winding dirt road that goals uphill in a desert area.  At the beginning, "START" is painted on the roadway.

If there was a question that ever made me start feeling old, it might be this one. Last week, Marcel Bootsman asked via Twitter, “Why did you start to use WordPress?”

WordPress community members chimed in with all sorts of reasons for hopping aboard, and Jeff Chandler of WP Mainline shared his journey on his site. These are the sort of discussions of nostalgia that I live for. What follows is my story.

I began blogging in 2003. A friend had introduced me to a now-defunct service called Expage. We mostly used it similarly to the early Myspace craze, adding things such as shout-outs to friends, random GIFs, scrolling marquee text, and midi files that blared as soon as a visitor landed on the page. But, I soon began learning how to link together multiple “Expages” (you only got one page), eventually building something of a journal.

After realizing the limitations of creating multiple accounts and passwords for different pages, I found Yahoo! GeoCities. After a short-lived stint with the service and being stifled by its roadblocks, I soon upgraded to a web hosting plan offered by Yahoo! with full PHP support. That meant I could do dynamic things like having multiple text files to store my blog post entries.

Thus, began my journey into building my own blogging system. Over the next couple of years, I kept my online journal open to the world with what felt like duct tape and old-fashioned grit. I tried WordPress at some point along the way and took a dive into PHP-Nuke and a couple of others. I then jumped back to my own system. I knew just enough PHP to be a flashing beacon for hacker-bots to push those little blue pills if they had ever bothered looking in my direction. Of course, my blog was so obscure that its glaring security holes did not register on any radar.

It was a week after I turned 21. On May 8, 2005, I had decided to get serious — yet again — about fixing my digital playground of a website. I would ditch any efforts of moving everything over to WordPress or another CMS. I was a lone wolf and was going to trek into the world wild web with nothing but my existing knowledge and instincts.

It was a fun era on the web for me. I was also a college student with an ever-changing list of interests, often varying by the day. Building a custom blogging system has never been an easy feat, and managing it all through plain text files had become a burden.

A mere five days later, I caved on my dream of managing a custom platform, but I needed to do so for my own sanity.

I simply began using WordPress because it made it easy to manage blog posts.

There were no special features like the editor, custom post types, or anything else that has brought so many others to the project. It was simply having a nicely organized posts management screen and the output of those posts on the front end. Relative to other systems at the time, it was also easy to install.

At the time, I probably did not think much of it. It was just another project in a line of others that I had tested, but I am happy I took the leap. WordPress has given me a career and, often, a purpose in life. It allowed me to grow as a developer, designer, and writer.

It may be blasphemy to say such things in WordPress circles, but my personal blog no longer runs on our beloved platform. After all these years, I have come full circle. My original goal was to build a flat-file blogging system, even though I did not know there was a name for such a thing back in the early-to-mid 2000s. I also did not have the requisite knowledge to build it at the time. However, in 2018, I coded my own system from scratch, and I loved every minute of that initial build. In part, I had a new project to tinker with, but it also carried a bit of the nostalgic factor of re-pioneering my early foray into the web.

While a custom blogging platform works for my own purposes, it makes me appreciate WordPress even more. It is hard to understand how much work goes into something as seemingly simple as the front-end architecture until you build it from the ground up. And, let us just skip over any talk of creating a secure and accessible admin interface that is user-friendly.

For any serious endeavor, WordPress is still my go-to solution — my personal site is a playground where I can afford to break things, after all. After our 16-year relationship, I do not see that changing at any point soon. As always, something exciting is around the corner. The platform keeps me on my toes, and I cannot imagine a world without it.

How or why did you begin using WordPress?

Forminator Pro now has Stripe Subscriptions for Recurring Payments, Pricing Plans, and Much More!

With Forminator Pro’s Stripe Subscriptions, recurring payments, pricing plans, and other improvements, your payment forms just got better! Learn how to implement these amazing features and hear about some other recent advancements in this article.

Forminator Pro, our popular form-creating plugin, just keeps improving with its new subscription payments options. It coordinates with Stripe, making managing and implementing recurring payments more effortless than ever.

This feature works for one-time payments and subscriptions. Plus, you can include free trials, customize subscription terms, add multiple payment structures, and more!

We’ll be going over:

You’ll see how Forminator Pro’s payment features can benefit your business today and other advanced options.

How to Add Stripe Subscriptions to Collect Recurring Payments

Subscriptions are perfect for gym memberships, donations, food boxes, book subscriptions — you name it. There are many reasons to include a subscription on your WordPress site, and now with Forminator, it’s a breeze!

Subscriptions can get set up by going to the Add-Ons section in Forminator’s dashboard. From here, it’s just a matter of clicking Install from the Forminator Stripe Subscription Add-On.

Forminator Stripe subscriptions add-on button.
It will tell you whether the add-on is installed or not, too.

At this point, you click Activate.

Where you activate the subscription option.
Don’t want to activate it yet? Click Close and come back at any time.

If you don’t have your Stripe account connected, you will do so here. You’ll fill in the required information, including your Test Publishable Key, Test Secret Key, Live Publishable Key, and Live Secret Key.

Where you connect your stripe account.
Once your information is added, you’ll hit Connect.

If you need any help setting up your Stripe account, we have you covered in our documentation.

Adding Multiple Pricing Plans

Multiple pricing plans are perfect if you want someone to pay in a given timeframe (e.g. every month), add extra orders, buy additional subscriptions for gifts, including a free trial, and more.

It’s up to you how you want to set up plans for your subscriptions.

Get started by heading to Forminator’s dashboard, go to Forms, and create or edit a form that you already have.

I went ahead and set up a new form called Forminator Subscription.

Where you name the new form.
Fitting name, I’d say.

For this example, let’s say that I want to take subscription payments with the options of Monthly, Quarterly, and Annually. I set up all the fields that I felt were necessary for this type of form.

The fields to include.
The essential information is included.

You’ll notice the Membership Plans field. That was created with a Select field, where I entered the various membership options and labeled it Membership Plans.

Various membership plans.
Three plans are available.

Now we include the Stripe field and edit its settings.

The Stripe field.
The Stripe field is in the mix with the rest of the fields.

In the Settings tab in the Stripe field, you go to the Payment Plan section and add different plans in the Plan Setup. We’ll go ahead and set up a Monthly option…

Where you set up a monthly plan.
We’ll start with the Monthly plan.

Now it’s time to choose a Payment Type. You can choose between One Time or Subscription. It’s then time to decide if you’d like a Fixed or Variable amount.

In this article, we’ll set up a monthly payment plan that costs $25. It’s just a matter of choosing Subscription and entering the Fixed monthly payment in the Amount box.

The payment type and amount box.
Enter any amount you want!

From here, you choose a Quantity. Pick a fixed amount or variable — whatever is best for your specific needs.

Quantity area.
We’ll use just one for this example.

And now, we’re ready to choose a billing cycle. You can decide how often to bill by:

  • Day(s)
  • Week(s)
  • Month(s)
  • Year(s)
Where you pick how often to bill.
Days, weeks, months, or years — the choice is yours when to bill!

There’s also an option for a Trial Period. Just check the box!

Selecting this option will give the user a limited-time free trial for a specific plan. For the time being, let’s allow for a 7-day trial. So, I’ll enter a ‘7’ in the Trial Duration area.

Where you pick a trial period.
Pick a reasonable trial period that works for you and your users.

Next, we’re going to head to the Conditions tab to connect it to our dropdown selection. This tab is in all of your subscription options. In this case, we’re on the Monthly subscription.

The conditions tab.
The Conditions tab is right next to Plan Setup.

From here, you add the condition(s) selections from the dropdown.

Conditions area.
This shows all of the fields I have inserted.

Conditions can be adjusted and changed however you’d like. For more information on how to specify what conditions are and how they function, be sure to check out our documentation.

To sync everything with Stripe, under the Advanced tab in the Stripe Field, scroll down, and you can select the Billing Details, where you choose your appropriate fields from the dropdown (e.g. Name, Email, etc.).

The billing details.
The dropdowns will contain the suggested fields to include.

Use the Meta Data area to include any other additional information that you’ll need from your users. This information will be sent to Stripe and appear in the MetaData section of every transaction.

For example, add a Phone Number.

The meta data area.
You’ll include any fields that you want.

Once you have all of the Meta Data you want to collect, you’re all set to publish your form!

Viewing Your Subscription Information in Stripe

What’s remarkable is how the information syncs with Stripe. This makes it easy to manage your subscriptions, see sales, get users’ information, and much more.

From Stripe’s dashboard, you check out who signed up under the Customers tab. You’ll be able to view the email, trial end date, invoice number, credit card info, and all additional information you need.

The subscription details in Stripe.
As you can see, Forminator signed up for a subscription!

On top of that, you can see all of the subscriptions that you created in the Products area.

The products area in Stripe.
You can see the Yearly, Quarterly, and Monthly subscriptions.

All of this can be viewed in test data and live mode, making for smooth operations as you start collecting payment for your subscriptions!

Subscription Example

To get an idea of the possibilities with recurring subscriptions and payments, here’s an example of a book box membership created with Forminator.

A book club webpage.
A user enters exactly what they want.

As you can see, there are a lot of options and variables to choose from. Users decide whether to get hardcover only and extra items (e.g. coffee, bookmark, etc.). When it comes to subscription options, you can choose between 3, 6, and 12 months.

The form also gives a running total of the price.

It goes without saying that setting up an appealing subscription option can be a game-changer when it comes to your sales.

If you’d like to test out this specific template for yourself, upload the code for it into Forminator’s dashboard and give it a try! Get the code here to check it out.

Using Localization Number Formatting

Another advanced feature that’s now included with Forminator Pro is the option to use localized number formatting.

This feature is available for the Number, Currency, and Calculations fields. In these fields, you can edit the number format under the Settings > Formatting.

You choose your decimal separator from the Separator dropdown. From here, you’ll have numerous options for decimals and commas, including not having them in specific spaces.

The separators section.
You get to choose how you want to format your numbers.

Pick what decimals you want to round to in the — you guessed it — Round To section. You choose between 0-4.

Where you round the decimals off.
Totally up to you how many decimals to round to.

Finally, you can also pre-populate this field dynamically using the query parameter passed in your form URL. Just enter it in the Query Parameter area (e.g. query_parameter_key).

The pre-populate area.
Add any query parameter that you’d like.

Localization number formatting gives you more control of how the value of your field is displayed.

Other Features

Forminator Pro released some other advanced features that you will find beneficial. They include:

    • Stripe and PayPal Options In a Single Form
    • Quizzes Accessibility for Videos and Images

Let’s check them out!

Stripe and PayPal Options In a Single Form

Instead of having just one or the other, you can now include both Stripe and PayPal. They can be included as payment options for your users on a single form.

Just add the Stripe and PayPal fields to any form as a payment option. You can also use the Select field to provide a dropdown of the options.

The dropdown makes it simple for a user to choose their preferred payment.

Quizzes Accessibility for Videos and Images

Want to spice up your quizzes? Add videos in quiz answers! This is useful for various purposes (e.g. a correct answer to a scene in a movie, what a particular song is, etc.) and can provide added engagement.

It’s done by adding a link to a video on YouTube or elsewhere. Then, it’s just a matter of including the link to the video in the Description area.

The video URL.
Add text on top and the link below!

You can always arrange the quiz order from Forminator’s dashboard under Appearance > Layout > Quiz Item Ordering. This is beneficial for arranging if you need the video to appear first or want the description at the top of the question.

The quiz alignment area.
Simply drag and drop to arrange.

And just like that, you’ll have videos added to your quiz!

Forminator Pro’s Features Are Something To Subscribe To

With recurring payment options, more payment options, and the inclusion of videos for quizzes, your forms for your WordPress site will go beyond the norm!

Plus, there are new advanced features always in the works. Be sure to check out our Roadmap for a glimpse of what’s coming next.

Forminator Pro is worth subscribing to. Really though, you don’t need to “subscribe” — it comes with every WPMU DEV membership (which you can try free for 7-days).

Rutter API Aims to Simplify E-Commerce Integration

Rutter, an API provider that specializes in e-commerce solutions, has announced the closing of a new funding round that is meant to bolster the company’s drive toward providing a unified API for e-commerce infrastructure. The Rutter API aims to simplify integration with myriad e-commerce platforms by removing the need to manually code individual connections.

React 18: Things You Need To Know About React JS Latest Version

The most awaited version of React 18 is finally out now. Its team has finally revealed the alpha version of React 18 and its plan, though the official launch is still pending. This time the team has tried something and released the plan first to know their user feedback because the last version of React 17 was not that much appreciated among developers.

According to Front-end Frameworks Survey, React JS has ranked top in the list of most loved frameworks. Thus, the developer communities expect a bit higher from the framework, so they are less appreciative of the previous launch.

Markdown autodocs: Automation From External or Remote Files

Why Markdown-autodocs

To make your repo more appealing and useful, you need to provide example code snippets in your README.md. It would be inefficient and time-consuming to manually copy and paste each code snippet in its respective place in your README.

This problem can be solved using Markdown-autodocs: a GitHub Action that automatically generates and updates markdown content (like your README.md) from external or remote files. You will need to add markers in your README.md that will tell markdown-autodocs where to insert the code snippet.

Scrollbar Reflowing

This is a bit of advice for developers on Macs I’ve heard quite a few times, and I’ll echo it: go into System Preferences > General > Show scroll bars and set to always. This isn’t about you, it’s about the web. See, the problem is that without this setting on, you’ll never experience scrollbar-triggered layout shifts, but everyone else with this setting on will. Since you want to design around not causing this type of jank, you should use this setting yourself.

Here’s Stefan Judis demonstrating that usage of viewport units can be one of the causes:

There, 100vw causes horizontal overflow, because the vertical scrollbar was already in play, taking up some of that space. Feels incredibly wrong to me somehow, but here we are.

Stefan points to Kilian Valkhof’s article about dealing with this. The classic fixes:

The easy fix is to use width: 100% instead. Percentages don’t include the width of the scrollbar, so will automatically fit.

If you can’t do that, or you’re setting the width on another element, add overflow-x: hidden or overflow: hidden to the surrounding element to prevent the scrollbar.

Kilian Valkhof, “How to find the cause of horizontal scrollbars”

Those are hacks, I’d say, since they are both things that aren’t exact matches for what you were wanting to do.

Fortunately, there is an incoming spec-based solution. Bramus has the scoop:

A side-effect when showing scrollbars on the web is that the layout of the content might change depending on the type of scrollbar. The scrollbar-gutter CSS property —which will soon ship with Chromium — aims to give us developers more control over that.

Bramus Van Damme, “Prevent unwanted Layout Shifts caused by Scrollbars with the scrollbar-gutter CSS property”

Sounds like the trick, and I wouldn’t be surprised if this becomes a very common line in reset stylesheets:

body {
  scrollbar-gutter: stable both-edges;
}

That makes me wonder though… it’s the <body> when dealing with this at the whole-page level, right? Not the <html>? That’s been weird in the past with scrolling-related things.

Are we actually going to get it across all browsers? Who knows. Seems somewhat likely, but even if it gets close, and the behavior is specced, I’d go for it. Feels progressive-enhancement-friendly.


The post Scrollbar Reflowing appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

Architecting With Next.js

(This is a sponsored post.)

Free event hosted by Netlify coming up next week (Wednesday, August 25th): Architecting with Next.js. It’s just a little half-day thing. No brainer.

Join us for a special event where we’ll highlight business teams using Next.js in production, including architecture deep dives, best practices and challenges. Next.js is the fastest-growing framework for Jamstack developers. With a compelling developer experience and highly performant results, it’s an emerging choice for delivering customer-facing sites and apps.

Next.js is such a nice framework, it’s no surprise to me it’s blowing up. It’s in React, a framework familiar to tons of people, thus enabling component-based front-ends, with common niceties built right in, like CSS modules. It produces HTML output, so it’s fast and good for SEO. It has smart defaults, so you’re rarely doing stuff like schlubbing your way through webpack config (unless you need that control, then you can). It does basic routing without you having to code it. Good stuff.

Direct Link to ArticlePermalink


The post Architecting With Next.js appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

How to use the Switch Expression in Java 14

Introduction

Java 14 was released with a new type of expression called Switch Expression. Its syntax is similar to that of the Switch Statement, with a few differences.

In this tutorial, we will walk through concepts related to the Switch Expression and learn how to use it.

Goals

At the end of this tutorial, you would have learned:

  1. The following concepts of Switch Expression: Arrow Label and Yielding.
  2. How to use the Switch Expression.
Prerequisite Knowledge
  • Basic Java.
Tools Required
  • An IDE with support for JDK 14+
Project Setup

Before writing any code, we need to set up our project first. Below are the steps to set up our project:

  1. Create a new vanilla Java project.
  2. Create the package com.example.switcher. This is where our main method lives.
  3. Create a public Java class Entry.java.
  4. Add the main method to Entry.java.
  5. Add an enum Season with 4 constants representing 4 seasons SPRING, SUMMER, FALL, WINTER. This enum has the package-private access modifier.

Your code should now look like this.

    package com.example.switcher;

    public class Entry {

       public static void main(String[] args){

       }

    }

    enum Season { SPRING, SUMMER, FALL, WINTER }
The Arrow Label

The first concept that we will look at is the arrow label. Instead of the colon label : used in switch statements, an arrow -> indicates that the current switch block is a Switch Expression.

Copy the 2 methods below into the Entry class to see how it is used.

    private static void arrowSwitch(Season season){
       switch(season){
           case SPRING -> System.out.println("It is Spring.");
           case SUMMER -> System.out.println("It is Summer.");
           case FALL -> System.out.println("It is Fall.");
           case WINTER -> System.out.println("It is Winter");
       }
    }

    private static Season arrowSwitch2(Season season){
       return switch (season){
           case SPRING -> Season.SPRING;
           case SUMMER -> Season.SUMMER;
           case FALL -> Season.FALL;
           case WINTER -> Season.WINTER;
       };
    }

Inside main(), they are called like this:

    public static void main(String[] args){
       arrowSwitch(Season.SPRING);
       System.out.println(arrowSwitch2(Season.FALL));
    }

And the output is:

It is Spring.
FALL

Here are the explanations for the code above:

  1. The first method arrowSwitch() is meant as a simple comparison to the switch statement. If you have not noticed, there is no break keyword and the case statements do not fall through. In a switch expression, there is only one matching case and the expression exits when a matching case is found, so we do not have to worry about the fall-through behavior of the old switch statement.
  2. The second method arrowSwitch2() is meant to show another behavior of switch expressions. Because they are expressions, they evaluate to a value, so it is possible to return a switch expression directly.
The yield Statement

Even though the arrow label -> definitely makes a switch block a switch expression, that does not mean the colon label : cannot be used inside a switch expression.

A colon label can be used inside a Switch Expression, but this syntax reintroduces the fall-through behavior and developers must use the yield keyword to cause the expression to evaluate to a value, therefore stop falling through.

Add the method below to the Entry class.

    private static Season colonSwitchExpression(Season season){
       return switch (season){
           case SPRING:
               System.out.println("It is Spring.");
               //yield Season.SPRING;
           case SUMMER:
               System.out.println("It is Summer.");
               //yield Season.SUMMER;
           case FALL:
               System.out.println("It is Fall.");
               //yield Season.FALL;
           case WINTER:
               System.out.println("It is Winter");
               yield Season.WINTER;
       };
    }

And call it in main() like the snippet below.

    public static void main(String[] args){
       //arrowSwitch(Season.SPRING);
       //System.out.println(arrowSwitch2(Season.FALL));
       colonSwitchExpression(Season.SPRING);
    }

And the program will print all the sysout calls because after matching with SPRING, the switch expression keeps falling through until it finds a yield statement.

It is Spring.
It is Summer.
It is Fall.
It is Winter

If we uncomment the 3 yield statements in the code above, then the switch expression will stop falling through.

It is recommended to always use the arrow label -> with switch expressions to avoid accidental fall through.

Solution Code
    package com.example.switcher;

    public class Entry {

       public static void main(String[] args){
           //arrowSwitch(Season.SPRING);
           //System.out.println(arrowSwitch2(Season.FALL));
           colonSwitchExpression(Season.SPRING);
       }

       private static void arrowSwitch(Season season){
           switch(season){
               case SPRING -> System.out.println("It is Spring.");
               case SUMMER -> System.out.println("It is Summer.");
               case FALL -> System.out.println("It is Fall.");
               case WINTER -> System.out.println("It is Winter");
           }
       }

       private static Season arrowSwitch2(Season season){
           return switch (season){
               case SPRING -> Season.SPRING;
               case SUMMER -> Season.SUMMER;
               case FALL -> Season.FALL;
               case WINTER -> Season.WINTER;
           };
       }

       private static Season colonSwitchExpression(Season season){
           return switch (season){
               case SPRING:
                   System.out.println("It is Spring.");
                   yield Season.SPRING;
               case SUMMER:
                   System.out.println("It is Summer.");
                   yield Season.SUMMER;
               case FALL:
                   System.out.println("It is Fall.");
                   yield Season.FALL;
               case WINTER:
                   System.out.println("It is Winter");
                   yield Season.WINTER;
           };
       }

    }

    enum Season { SPRING, SUMMER, FALL, WINTER }
Summary

In this tutorial, we have learned how to use the Switch Expression that was released alongside JDK 14.

The full project code can be found at https://github.com/dmitrilc/DaniWebJavaSwitchExpression

Java – How to create a JPMS Module

Introduction

In this tutorial, we are going to learn how to create a Java module by hand.

Goals

At the end of this tutorial, you would have learned:

  1. What a module-info.java file is.
  2. How to compile a module.
  3. Describing a module.
Prerequisite Knowledge
  1. Basic Java.
  2. Basic command-line interface.
Tools Required
  1. A CLI shell, such as Command Prompt for Windows, Terminal for Mac, or Bash for Linux.
  2. JDK 9+ path/environment variables already setup.
Concept Overview

Java Module is an abstraction on top of packages that allows for more fine-grained encapsulation.

In the module-info.java file that defines every module, we can restrict the modules dependencies, the packages that it exports, services that it consumes or offers, and whether it allows reflection.

The Bank Example

In order to see the concept of modules in action, we will create an example module. For learning purposes, we will not be using an IDE at all in this tutorial.

Let us assume that we are writing software for a bank. This bank has a software engineering team responsible for security.

The module that the security team creates is responsible for:

  1. Biometrics(information).
  2. Vault(security).

To give you a rough idea, later on, we are going to create the following modules and packages:

module: com.bank.security
package: com.bank.security.biometrics
package: com.bank.security.vault
The Security Module

First we will start with creating the security module.

  1. Create a folder called example. This is where all of our modules live.

  2. Under example, create the following directories(recursively):
    a. com/bank/security/biometrics
    b. com/bank/security/vault

  3. Under com/bank/security, create a module-info.java file. This file contains the definitions for your com.bank.security module. You do not have to understand this file for now. I will explain it in the next section.

     module com.bank.security {
     }
  4. Under biometrics, create a Fingerprint.java file. The file only needs two lines, a package declaration and an empty class.

     package com.bank.security.biometrics;
     public class Fingerprint {}
  5. Under vault, create a Guard.java file. This file also does not contain anything significant.

     package com.bank.security.vault;
     public class Guard {}

Your directory tree should now look like this

.
 example
     com
         bank
             security
                biometrics
                   Fingerprint.java
                module-info.java
                vault
                    Guard.java
The module-info.java File

At the minimum, a module-info.java file must include the module name. The module name is declared right after the module keyword.

    module com.bank.security

There are four types of modules.

  1. System modules: modules that came with the JDK.
  2. Automatic modules: regular jar files that are added to the module path(not the same as class path)
  3. Unnamed modules: a catch-all module that includes every jar file on the class path.
  4. Application modules: modules with the module-info.java file that application developers can create.

The com.bank.security module that we just created is an example of an application module.

Compiling the Security module

To compile the security module, we would navigate back to the directory before the example directory, and use the below javac command:

    javac -d compiled example/com/bank/security/biometrics/Fingerprint.java example/com/bank/security/vault/Guard.java example/com/bank/security/module-info.java

You should now see a directory named compiled that contains compiled class files, including the module-info.class.

The compiled directory should look like the tree below.

 compiled
    com
       bank
           security
               biometrics
                  Fingerprint.class
               vault
                   Guard.class
    module-info.class
The exports Directive

Let us try to apply a common module directive: exports. Modify the module-info.java file and add the exports directive.

    module com.bank.security {
        exports com.bank.security.biometrics;
    }

This exports directive allows any other module to read the biometrics package. Without it, other modules would not be able to use the biometrics package normally.

Packaging a module

Next we will package our compiled module into a jar file.

  1. Make a directory called modules. This is where we will place the packaged jar.

  2. Run the command below to package everything under the compiled directory into a jar.

     jar -cvf modules/com.bank.security.jar -C compiled/ .

If you navigate to the modules directory, you will see the com.bank.security.jar file.

Describing a module

Lastly, we will use a java command to describe our module definitions.

    java -p modules --describe-module com.bank.security

After running the above command, you will see the information below.

    exports com.bank.security.biometrics
    requires java.base mandated
    contains com.bank.security.vault

The exports line indicates the package biometrics that we have exported earlier.
The requires line indicates that our module depends on the java.base module. All Java modules implicitly require java.base.
The contains line lists a package that is not exported at all, so this package is only usable to code inside the same module, under normal circumstances.

Solution Code

The whole project zip file can be downloaded here https://github.com/dmitrilc/DaniWebModule

Summary

We have learned how to create our own custom Java module in this tutorial. I skipped the IDE because I believe that compiling by hand is the best way to learn modules.

Quiz Application for vb.NET

Good afternoon,

I'm haven't coded in a very long time, and now I have some time in my life I'm actually coding a Quiz application in vb.net using ms access for the question/answer database. This project is what the student will see when their taking the test, and my issue is I'm having trouble with loading the questions into the form, and grading when finished. I really apperciate any feedback due to I'm trying to learn..

Thanks,
Gerard

Progressive Delivery: A Detailed Overview

Every developer has been there before: You release a new feature expecting a smooth ride, only to have something go awry in the back end at the last minute. 

An event like this can derail a launch, letting down customers and leaving you scratching your head wondering what went wrong.

Introduction to the Solid JavaScript Library

Solid is a reactive JavaScript library for creating user interfaces without a virtual DOM. It compiles templates down to real DOM nodes once and wraps updates in fine-grained reactions so that when state updates, only the related code runs.

This way, the compiler can optimize initial render and the runtime optimizes updates. This focus on performance makes it one of the top-rated JavaScript frameworks.

I got curious about it and wanted to give it a try, so I spent some time creating a small to-do app to explore how this framework handles rendering components, updating state, setting up stores, and more.

Here’s the final demo if you just can’t wait to see the final code and result:

Getting started

Like most frameworks, we can start by installing the npm package. To use the framework with JSX, run:

npm install solid-js babel-preset-solid

Then, we need to add babel-preset-solid to our Babel, webpack, or Rollup config file with:

"presets": ["solid"]

Or if you’d like to scaffold a small app, you can also use one of their templates:

# Create a small app from a Solid template
npx degit solidjs/templates/js my-app
 
# Change directory to the project created
cd my-app
 
# Install dependencies
npm i # or yarn or pnpm
 
# Start the dev server
npm run dev

There is TypeScript support so if you’d like to start a TypeScript project, change the first command to npx degit solidjs/templates/ts my-app.

Creating and rendering components

To render components, the syntax is similar to React.js, so it might seem familiar:

import { render } from "solid-js/web";
 
const HelloMessage = props => <div>Hello {props.name}</div>;
 
render(
 () => <HelloMessage name="Taylor" />,
 document.getElementById("hello-example")
);

We need to start by importing the render function, then we create a div with some text and a prop, and we call render, passing the component and the container element.

This code then compiles down to real DOM expressions. For example, the code sample above, once compiled by Solid, looks something like this:

import { render, template, insert, createComponent } from "solid-js/web";
 
const _tmpl$ = template(`<div>Hello </div>`);
 
const HelloMessage = props => {
 const _el$ = _tmpl$.cloneNode(true);
 insert(_el$, () => props.name);
 return _el$;
};
 
render(
 () => createComponent(HelloMessage, { name: "Taylor" }),
 document.getElementById("hello-example")
);

The Solid Playground is pretty cool and shows that Solid has different ways to render, including client-side, server-side, and client-side with hydration.

Tracking changing values with Signals

Solid uses a hook called createSignal that returns two functions: a getter and a setter. If you’re used to using a framework like React.js, this might seem a little weird. You’d normally expect the first element to be the value itself; however in Solid, we need to explicitly call the getter to intercept where the value is read in order to track its changes.

For example, if we’re writing the following code:

const [todos, addTodos] = createSignal([]);

Logging todos will not return the value, but a function instead. If we want to use the value, we need to call the function, as in todos().

For a small todo list, this would be:

import { createSignal } from "solid-js";
 
const TodoList = () => {
 let input;
 const [todos, addTodos] = createSignal([]);
 
 const addTodo = value => {
   return addTodos([...todos(), value]);
 };
 
 return (
   <section>
     <h1>To do list:</h1>
     <label for="todo-item">Todo item</label>
     <input type="text" ref={input} name="todo-item" id="todo-item" />
     <button onClick={() => addTodo(input.value)}>Add item</button>
     <ul>
       {todos().map(item => (
         <li>{item}</li>
       ))}
     </ul>
   </section>
 );
};

The code sample above would display a text field and, upon clicking the “Add item” button, would update the todos with the new item and display it in a list.

This can seem pretty similar to using useState, so how is using a getter different? Consider the following code sample:

console.log("Create Signals");
const [firstName, setFirstName] = createSignal("Whitney");
const [lastName, setLastName] = createSignal("Houston");
const [displayFullName, setDisplayFullName] = createSignal(true);
 
const displayName = createMemo(() => {
 if (!displayFullName()) return firstName();
 return `${firstName()} ${lastName()}`;
});
 
createEffect(() => console.log("My name is", displayName()));
 
console.log("Set showFullName: false ");
setDisplayFullName(false);
 
console.log("Change lastName ");
setLastName("Boop");
 
console.log("Set showFullName: true ");
setDisplayFullName(true);

Running the above code would result in:

Create Signals
 
My name is Whitney Houston
 
Set showFullName: false
 
My name is Whitney
 
Change lastName
 
Set showFullName: true
 
My name is Whitney Boop

The main thing to notice is how My name is ... is not logged after setting a new last name. This is because at this point, nothing is listening to changes on lastName(). The new value of displayName() is only set when the value of displayFullName() changes, this is why we can see the new last name displayed when setShowFullName is set back to true.

This gives us a safer way to track values updates.

Reactivity primitives

In that last code sample, I introduced createSignal, but also a couple of other primitives: createEffect and createMemo.

createEffect

createEffect tracks dependencies and runs after each render where a dependency has changed.

// Don't forget to import it first with 'import { createEffect } from "solid-js";'
const [count, setCount] = createSignal(0);
 
createEffect(() => {
 console

Count is at... logs every time the value of count() changes.

createMemo

createMemo creates a read-only signal that recalculates its value whenever the executed code’s dependencies update. You would use it when you want to cache some values and access them without re-evaluating them until a dependency changes.

For example, if we wanted to display a counter 100 times and update the value when clicking on a button, using createMemo would allow the recalculation to happen only once per click:

function Counter() {
   const [count, setCount] = createSignal(0);
   // Calling `counter` without wrapping it in `createMemo` would result in calling it 100 times.
   // const counter = () => {
   //    return count();
   // }
 
   // Calling `counter` wrapped in `createMemo` results in calling it once per update.
// Don't forget to import it first with 'import { createMemo } from "solid-js";'
   const counter = createMemo(() => {
       return count()
   })
 
   return (
       <>
       <button onClick={() => setCount(count() + 1)}>Count: {count()}</button>
       <div>1. {counter()}</div>
       <div>2. {counter()}</div>
       <div>3. {counter()}</div>
       <div>4. {counter()}</div>
       <!-- 96 more times -->
       </>
   );
}

Lifecycle methods

Solid exposes a few lifecycle methods, such as onMount, onCleanup and onError. If we want some code to run after the initial render, we need to use onMount:

// Don't forget to import it first with 'import { onMount } from "solid-js";'
 
onMount(() => {
 console.log("I mounted!");
});

onCleanup is similar to componentDidUnmount in React — it runs when there is a recalculation of the reactive scope.

onError executes when there’s an error in the nearest child’s scope. For example we could use it when fetching data fails.

Stores

To create stores for data, Solid exposes createStore which return value is a readonly proxy object and a setter function.

For example, if we changed our todo example to use a store instead of state, it would look something like this:

const [todos, addTodos] = createStore({ list: [] });
 
createEffect(() => {
 console.log(todos.list);
});
 
onMount(() => {
 addTodos("list", [
   ...todos.list,
   { item: "a new todo item", completed: false }
 ]);
});

The code sample above would start by logging a proxy object with an empty array, followed by a proxy object with an array containing the object {item: "a new todo item", completed: false}.

One thing to note is that the top level state object cannot be tracked without accessing a property on it — this is why we’re logging todos.list and not todos.

If we only logged todo` in createEffect, we would be seeing the initial value of the list but not the one after the update made in onMount.

To change values in stores, we can update them using the setting function we define when using createStore. For example, if we wanted to update a todo list item to “completed” we could update the store this way:

const [todos, setTodos] = createStore({
 list: [{ item: "new item", completed: false }]
});
 
const markAsComplete = text => {
 setTodos(
   "list",
   i => i.item === text,
   "completed",
   c => !c
 );
};
 
return (
 <button onClick={() => markAsComplete("new item")}>Mark as complete</button>
);

Control Flow

To avoid wastefully recreating all the DOM nodes on every update when using methods like .map(), Solid lets us use template helpers.

A few of them are available, such as For to loop through items, Show to conditionally show and hide elements, Switch and Match to show elements that match a certain condition, and more!

Here are some examples showing how to use them:

<For each={todos.list} fallback={<div>Loading...</div>}>
 {(item) => <div>{item}</div>}
</For>
 
<Show when={todos.list[0].completed} fallback={<div>Loading...</div>}>
 <div>1st item completed</div>
</Show>
 
<Switch fallback={<div>No items</div>}>
 <Match when={todos.list[0].completed}>
   <CompletedList />
 </Match>
 <Match when={!todos.list[0].completed}>
   <TodosList />
 </Match>
</Switch>

Demo project

This was a quick introduction to the basics of Solid. If you’d like to play around with it, I made a starter project you can automatically deploy to Netlify and clone to your GitHub by clicking on the button below!

This project includes the default setup for a Solid project, as well as a sample Todo app with the basic concepts I’ve mentioned in this post to get you going!

There is much more to this framework than what I covered here so feel free to check the docs for more info!


The post Introduction to the Solid JavaScript Library appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

How To Automate Documentation Workflow For Developers

To get the most out of this tutorial, you should be familiar with: Git, GitHub and Linux and the command line.

Why Should You Care About High-Quality Documentation?

Many teams struggle with writing documentation. When you go to check a framework, the documentation will often be out of date or unclear. This can lead to internal frustration when a team member tries to add a feature, but they don’t understand how the current feature works because of poor documentation. This can lead to unproductive hours on the job.

Poor documentation also compromises a good customer experience. According to Jeff Lawson, author of Ask Your Developer and founder of Twilio, if you are selling an API as a product, documentation is the ultimate advertisement for technical stakeholders. IBM did a study on the importance of documentation, and 90% of respondents admitted that they made their purchasing decisions based on the quality of a product’s documentation.

Writing good documentation is important for the developer and customer experiences.

If Documentation Is So Important, Then Why Do Engineering Teams Deprioritize It?

Writing documentation can break developers out of the “flow”. Documentation often lives outside of the main code base, and it is cumbersome to find and update. Putting it in an Excel spreadsheet or a proprietary CMS is not uncommon.

Automating documentation and improving documentation workflow fixes this.

Automating Documentation From a High Level

What does automating documentation mean? It means adopting common software development practices. When you automate documentation, you are:

  • writing your documentation in Markdown;
  • using a continuous integration and continuous deployment (CI/CD) pipeline to run tasks such as correcting errors and deploying updates (in this tutorial, we are going to highlight GitHub Actions);
  • implementing tools like Vale to enforce a style guide and to correct common grammatical mistakes.
The Style Guides

Before you use tools such as Vale and GitHub Actions to automate the style guide, let’s take a moment to define what exactly is a style guide.

You know that feeling when you are writing documentation and something seems a little off? Your explanations don’t fit the rest of the documentation, but you can’t quite describe why they’re wrong. The writing explains the concept, but it doesn’t seem to fit.

When you get this feeling, your voice and tone might be off. Refining the voice and tone is a way to make writing sound cohesive even if you are developing documentation that has been edited by the QA, engineering, and product teams. Below is an example style guide from the city bus application TAPP, taken from the book Strategic Writing for UX by Torrey Podmajersky.

TAPP is a transit application (for buses and trains). The header of the table announces TAPP’s values as a company, being efficient, trustworthy, and accessible. The left side of the table lists the different parts covered by the style guide: concepts, vocabulary, verbosity, grammar, and punctuation.

Together, these make a style guide. The header introduces the values, and the left side of the table shows the different components that you would find in any written material: vocabulary, grammar, and punctuation. The beauty of this style guide is that engineers and copywriters will clearly know what capitalization to use and which punctuation to use in order to promote Tapp’s brand identity.

Technical Writing Style Guide

Not all style guides come in tables. Microsoft has a whole website that serves as a comprehensive guide, covering everything from acronyms to bias-free communication to chatbots. Microsoft of course isn’t the only company that has a style guide. Google has one, too.

The Trouble With Style Guides

Style guides are a great starting point for companies that are serious about documentation. They solve a lot of the confusion that developers might have about how exactly to write about a major feature that they are pushing out.

The problem with style guides is that they add friction to the writing process. Many writers, including me, don’t bother to stop writing and look at the style guide every time they have a question. Sometimes, a style guide is cumbersome and too difficult to reference — for instance, the Microsoft Style Guide is over a thousand pages long!

Linters and CI/CD for Documentation

If you are a programmer, then you are probably familiar with linters. Linters are an ideal way to enforce coding standards on your team. The same is true with documentation. When you create a linter, you are setting a benchmark of quality for your documentation. In this tutorial, we are going to use the Vale linter.

Using some sort of documentation automation alongside a linter is common. When we say automation in this context, we’re referring to the continuous integration and continuous deployment (CI/CD) workflow. CI automates the building and testing of documentation. CD automates the release of code.

You can use many different types of apps to implement a CI/CD workflow. In this tutorial, we are going to use GitHub Actions to run our documentation linter. GitHub Actions run CI directly in a GitHub repository, so there is no need to use a third-party application, such as CircleCI or Travis.

Finally, GitHub Actions are event-driven, which means they are triggered when something happens, such as when someone writes a pull request or an issue. In our example, a GitHub action will occur when someone pushes changes to their main branch.

GitHub Actions

First, create a GitHub repository. Then, locally, create a folder and cd into it.

mkdir automated-docs
cd automated-docs

Once you are in the folder, initialize the directory for Git.

git init

Once you have initialized the repository, proceed to create a workflow directory to your folder.

mkdir .github/ && cd .github/ && mkdir workflows/ && cd workflows/

Workflows are where we will store all of our GitHub actions. Once you’ve created a workflows folder, make a new workflow. We are going to name this workflow vale.yml.

touch vale.yml

Vale.yml is a YAML file. In this workflow file, we will include actions and jobs.

Now, open vale.yml in your favorite text editor.

nano vale.yml

Copy and paste the following into vale.yml, and let’s go over the context and syntax.

# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events but only for the main branch
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      # Runs a single command using the runners shell
      - name: Run a one-line script
        run: echo Hello, world!

      # Runs a set of commands using the runners shell
      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.
        env:
          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
  • name
    This is the name, or what we are calling our workflow. It is a string.
  • on
    This controls the workflow and the triggers.
  • jobs
    This is where we set up and control our actions. We select the environment where our actions will run — it is usually a good bet to go with Ubuntu. And this is where we will add our actions.

GitHub has a guide on all of the other workflow syntax and variables, in case you’re curious.

In this section, we have:

  • learned what GitHub actions are,
  • created our first GitHub workflow,
  • identified the most important parts of a GitHub workflow YAML file.

Next, we are going to customize our GitHub workflow to use Vale.

Set Up Vale in GitHub Actions File

Once we’ve copied the base workflow file, it is time to customize it, so that we can start using Vale actions. The first thing to do is change the name of the YAML file to Docs-Linting.

# This is a basic workflow to help you get started with Actions.

name: Docs-Linting

Next, we want to run the Vale test once someone has pushed their changes to the main branch on GitHub. We don’t want the test to run when someone creates a pull request, so we’ll delete that part of the YAML file.

on:
  # Triggers the workflow on push or pull request events but only for the main branch
  push:
    branches: [ main ]

The jobs section is the main part of the workflow file, and it is responsible for running the GitHub actions.

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@master

These actions are going to run on the latest version of Ubuntu. The Checkout action checks out the repository in order for the GitHub workflow to access it.

Now it is time to add a Vale action to our GitHub workflow.

  - name: Vale
      uses: errata-ai/vale-action@v1.4.2
      with:
        debug: true
        styles: |
          https://github.com/errata-ai/write-good/releases/latest/download/write-good.zip
          https://github.com/errata-ai/Microsoft/releases/latest/download/Microsoft.zip

      env:
        GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

We have named our action Vale. The uses variable shows which version of Vale we’re going to implement — ideally, we should use the most recent version. In the with variable, we set debug to true.

The styles section gives us the option to add a style guide to Vale. In this example, we are going to use write-good and Microsoft’s official style guide. Keep in mind that we can use other style guides as well.

The final part of this GitHub action is env. In order to run this GitHub action, we need to include a secret token.

This is what the result should look like:

# This is a basic workflow to help you get started with Actions.

name: Docs-Linting

# Controls when the action will run.
on:
  # Triggers the workflow on push or pull request events but only for the main branch
  push:
    branches: [ main ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  prose:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@master

    - name: Vale
      uses: errata-ai/vale-action@v1.4.2
      with:
        debug: true
        styles: |
          https://github.com/errata-ai/write-good/releases/latest/download/write-good.zip
          https://github.com/errata-ai/Microsoft/releases/latest/download/Microsoft.zip

      env:
        GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

Once you’ve finished making changes, save the file, commit to Git, and push your changes to GitHub.

git add .github/workflows/vale.yml
git commit -m "Added github repo to project"
git push -u origin main

To recap, in this section, we have:

  • triggered the action to occur when we push new code to the main branch;
  • added a Vale action, setting debug to true and identifying style guides;
  • added a GitHub token;
  • committed changes and pushed to GitHub.

In the next section, we are going to create a Vale configuration file.

Setting Up Vale Configuration File

Go to the root of your project’s directory, and then touch .vale.ini. Open .vale.ini in a text editor. Copy and paste the following into .vale.ini:

StylesPath = .github/styles
MinAlertLevel = warning

[formats]
Markdown = markdown

[*.md]
BasedOnStyles = write-good, Microsoft
  • StylesPath = .github/styles
    The StylesPath gives the path of the Vale styles.
  • MinAlertLevel = warning
    The minimum alert level shows the scale of severity in alerts. The options are suggestion, warning, and error.
  • [formats]
    Markdown = markdown sets the format as Markdown.
  • [*.md]
    The configuration BasedOnStyles = write-good, Microsoft will run write-good and the Microsoft style guide on all Markdown files ending with .md.

This set-up is the bare minimum. If you are interested in learning more about configuring Vale, head over to the documentation.

When you are finished making changes, save the file, and commit and push to GitHub.

git add .vale.ini
git commit -m "Added Vale config file"
git push -u origin main

In this part, we’ve learned the internals of a Vale configuration file. Now it’s time to create sample documentation.

Creating Documentation and Triggering the Vale GitHub Actions

Now it is time to see Vale and GitHub Actions in action! We are going to create a Markdown file and fill it with text. And we are going to get our text from DeLorean Ipsum.

Go to the root of your project, and then touch getting-started.md. Once you’ve created the getting-started file, go to DeLorean Ipsum and create some dummy text for your documentation. Then, return to your text editor and paste the text in getting-started-md.

# Getting Started Guide

I can’t play. It’s my dad. They’re late. My experiment worked. They’re all exactly twenty-five minutes slow. Marty, this may seem a little foreward, but I was wondering if you would ask me to the Enchantment Under The Sea Dance on Saturday. Well, they’re your parents, you must know them. What are their common interests, what do they like to do together?

Okay. Are you okay? Whoa, wait, Doc. What, well you mean like a date? I don’t wanna see you in here again.

No, Biff, you leave her alone. Jesus, George, it’s a wonder I was ever born. Hey, hey, keep rolling, keep rolling there. No, no, no, no, this sucker’s electrical. But I need a nuclear reaction to generate the one point twenty-one gigawatts of electricity that I need. I swiped it from the old lady’s liquor cabinet. You know Marty, you look so familiar, do I know your mother?

Save the file, commit it, and push it to GitHub.

git add getting-started.md
git commit -m "first draft"
git push -u origin main

Once you’ve pushed the changes, head over to GitHub where your repository is located. Go to the Actions tab.

You will see all of your workflows on the left side. We have only one, named Docs-Linting, the same name we put in the vale.yml file.

When we push the documentation to GitHub, we will trigger the action.

If the action has run without any problems, we will get a green checkmark.

Click on “Added docs” to get a full report.

You will see that we got 11 warnings. Let’s deal with the “weasel word” warning. Go back to the text editor, open getting-started.md, and delete the word “exactly”.

# Getting Started Guide

I can’t play. It’s my dad. They’re late. My experiment worked. They’re all twenty-five minutes slow. Marty, this may seem a little foreward, but I was wondering if you would ask me to the Enchantment Under The Sea Dance on Saturday. Well, they’re your parents, you must know them. What are their common interests, what do they like to do together?

Okay. Are you okay? Whoa, wait, Doc. What, well you mean like a date? I don’t wanna see you in here again.

No, Biff, you leave her alone. Jesus, George, it’s a wonder I was ever born. Hey, hey, keep rolling, keep rolling there. No, no, no, no, this sucker’s electrical. But I need a nuclear reaction to generate the one point twenty-one gigawatts of electricity that I need. I swiped it from the old lady’s liquor cabinet. You know Marty, you look so familiar, do I know your mother?

Save the changes, commit it to Git, and push the new version of the file to GitHub. It should trigger the GitHub action.

If we click on “Deleted the weasel word”, we will see that we have only 10 warnings now, and the “weasel word” warning is gone. Hooray!

We are finished, and we’ve covered a lot of ground. In this section, we have:

  • added documentation to our Vale GitHub Actions repository,
  • triggered the Vale GitHub action,
  • corrected an error produced by Vale and pushed the change back to GitHub.
Conclusion

In a world that is increasingly going remote, prioritizing good documentation and good documentation workflow is important. You first have to define what “good” is by creating a style guide. Once you’ve figured out the rules of your documentation, then it’s time to automate.

Documentation should be treated like your code base: a living body of work that is constantly being iterated and becoming a bit better than the last time you updated it.

How to Create a Short Link in WordPress (The Easy Way)

Do you want to create short links to your WordPress blog posts or pages?

Short links are useful for sharing in your emails, Facebook messages, and even text messages.

In this article, we will show you how to generate short links using a plugin, and how to add the ‘Get Shortlink’ button back to the classic WordPress editor.

How to Create a Short Link in WordPress

Why Create a Short Link in WordPress?

Sharing your web content on social media can build user engagement and bring new users to your website. But pasting in long links or URLs isn’t always the best way.

That’s because some social media platforms will limit the number of characters you can use. A shorter URL gives you extra space for more useful content, which can lead to more engagement and traffic to your WordPress website.

That’s why URL shortener services like Bitly and TinyURL were originally created. They take a long link and make it shorter so that it doesn’t take up as much space.

For example, if you’re using SEO-friendly URL structures, then you might have long URLs that look something like this:

https://www.wpbeginner.com/beginners-guide/self-hosted-wordpress-org-vs-free-wordpress-com-infograph/

Our short link for that post saves a lot of space:

http://wpbeg.in/b6xh7G

Note: We’re using a custom domain, wpbeg.in, for our short links, which is a bit more technical to set up and would require you to purchase another domain. We have a separate tutorial on how to create your own customized short URL.

In the past, WordPress made it easy to get a short link to your blog post or page. There was a Get Shortlink button located right next to the permalink area of the classic editor.

Get Shortlink Button in the Classic Editor

However, if you recently started your blog, then you will not see this feature on your WordPress site because it was removed after WordPress version 4.4. WordPress still creates the links, but the button has been removed.

Still, there are a few ways you can get short links for your WordPress posts and pages.

We’ll cover the best link shortener plugin, plus a couple of ways you can restore the ‘Get Shortlink’ button in the classic editor. Simply click the links below to jump straight to each option:

We’ll start with a method that works for everyone. The Pretty Links plugin doesn’t rely on the classic editor and will create its own short link out of any URL.

It works with all links, including pages outside of your blog or website. So, besides letting you share your own content, it’s also the perfect tool for shortening affiliate links.

To get started, you’ll need to install and activate the Pretty Links plugin. For more details, see our step by step guide on how to install a WordPress plugin.

Note: There is a Pro version of Pretty Links with more powerful features like keyword auto-linking and link categories and tags, but for this tutorial we will be using the free version.

Once you activate the plugin, a Pretty Links section is added to your WordPress dashboard. To create your first short link, you need to go to the Pretty Links » Add Link page.

Next, you need to paste the original URL of the page you want to share into the Target URL text field. A short Pretty Link is automatically created, but you can customize it if you’d like to make it more readable.

Paste the Original URL Into Target URL

Once you’ve created a few short links, you may not remember what they are all for. So it’s a good idea to type in the title of the web page and consider writing some notes of anything you need to remember.

Fill in the Title and Notes

Once you have filled in the Pretty Links form, click the Update button to activate the short link.

Click the Update Button to Activate the Short Link

You will now see a list of all of your Pretty Links. To copy one to the clipboard, just click on the Copy icon at the right of the screen.

After that, you can paste it into any of your social media channels. Pretty Links will even keep track of how many clicks each link gets.

Copy the Short Link Using the Copy Icon

While pretty links have built-in analytics, you can further improve your analytics by connecting it with Google Analytics using the MonsterInsights plugins. For more details, see our step by step guide on how to properly set up Google Analytics in WordPress.

This is a simple method of adding back the Get Shortlink button to the classic editor.

First, you need to install and activate the Bring Back the Shortlink Button plugin. For more details, see our step by step guide on how to install a WordPress plugin.

Upon activation, this plugin will automatically add the Get Shortlink button to the classic editor. To check that it worked, just edit any of your posts.

The Get Shortlink Button is Added to the Classic Editor

When you click the Get Shortlink button, it will show you the WordPress Shortlink for your post or page. You can copy the link to the clipboard so you can share it with your audience in your emails and messages.

Copy the Short Link to Share It with Your Audience

This method is for more advanced users and uses code rather than a plugin. It adds the Shortlink button to the classic editor by adding a custom code snippet to your theme’s functions.php file.

We don’t recommend this method to inexperienced users because if you make a mistake, then it could break your website. Method 2 above is a simpler way to achieve the same result without needing to use code.

If this is your first time adding code to your WordPress files, then you should check out our guide on how to copy and paste code snippets in WordPress.

We’ll use the Code Snippets plugin mentioned in that guide, so you’ll need to install that first. For more details, see our step by step guide on how to install a WordPress plugin.

Upon activation, the plugin will add a new menu item labeled Snippets to your WordPress admin bar. Clicking on it will show you a list of all the custom code snippets you have saved on your site.

Go ahead and click on the Add New button to add your first custom code snippet in WordPress.

Click the Add New Button to Add Your First Custom Code Snippet in WordPress

This will bring you to the ‘Add New Snippet’ page.

You need to start by entering a title for your custom code snippet. Let’s call it ‘Short Link Button’. After you enter a title, simply copy and paste the code snippet below into the code box.

add_filter( 'get_shortlink', function( $shortlink ) {return $shortlink;} );

Copy and Paste the Code Snippet Into the Code Box

When you come across this snippet in the future, you may not remember what it’s for. So it’s a good idea to type something helpful in the description as a reminder.

Type Something Helpful in the Description

You can also assign tags to your code snippet. This will help you sort your code snippets by topic and functionality.

Finally, you need to click on the ‘Save Changes and Activate’ button. Once the snippet is activated, the Shortlink button will be added to the classic editor.

The Shortlink Button Will Be Added

We hope this article helped you learn how to create a short link in WordPress. You might also like to learn how to get a free email domain, or see our comparison of the best domain name registrars.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.

The post How to Create a Short Link in WordPress (The Easy Way) appeared first on WPBeginner.

How do I set the default content page on IIS/ASP?

How do I set the default index landing page (also known as the default content page) on a Classic ASP file?

While setting up a simple first Hello World style classic ASP program locally, I remember how things are set up on the server where I will eventually migrate my work to.

On the server, in IIs, when I right-click on a Web Site, I can see properties.

[img]https://i.stack.imgur.com/HLS0K.png[/img]

And that brings up a tabbed dialog box where one of the tabs is Documents

[img]https://i.stack.imgur.com/JqlzM.png[/img]

So, here, clearly I can set the name of the default content page. Naturally, I want to set this up locally on my Windows 10 computer.

Now, eventhough I believe I have set up IIS on my side. Things do now look the same on my side. I have a windows 10 Operating System and so I expect things will look a bit differently according to style. But I am hoping the functionality will be the same? Will the functionality be the same? On my end, on my Windows 10 computer, this is what I see when I right click on my web site? I do not see anything about "Properties" which would bring up a dialog box where I can set the default content page.

[img]https://i.stack.imgur.com/m6QQi.png[/img]

Please be so kind as to advise.

I know, or at least I have read online is, that classic ASP is part of IIS. So, here is the information I have gotten when I check the version of the ISS systems.

My local windows 10 iSS, help --> about menu selection produces this information:

[img]https://i.stack.imgur.com/cGuZ7.png[/img]

On the server, the IIS has two options that come up in the Help menu that I find interesting. They are "About Microsoft Management Console..." and "About Internet Information Service (IIS) Manager...

[img]https://i.stack.imgur.com/bEyrO.png[/img]

The information dialogs that come up when clicking on these are:

[img]https://i.stack.imgur.com/u9pLI.png[/img]

and

[img]https://tinyurl.com/8y3cdwfy[/img]

So, that is all I got thus far. How to I proceed in setting up my ASP development capacity locally?