Copy
What a Tool!

Issue #375 • September 24, 2020

The following intro tutorial was submitted by Erik Kückelheim, a self-taught developer living in Konstanz, Germany. In this write-up, Erik will describe how he built the editor used in his new website JSchallenger, which I featured in a recent issue.

Creating an online code editor can be tricky. I learned that while developing my JavaScript editor on JSchallenger. Here I'll present a step-by-step guide to the very basics of this editor. You can easily customize this setup in order to create your own similar app.

The first thing I need to do is get access to the HTML element that I want to turn into an editor so I can add the contenteditable attribute to allow user input:

const container = document.getElementById("container");

container.setAttribute("contenteditable", "true");

Next I'll initiate a listener for the input event that fires the handleInput function:

let timeout;

const debounce = (func, wait) => {
  clearTimeout(timeout);
  timeout = setTimeout(func, wait);
};

const handleInput = () => {
 
debounce(() => {
    format();
    setCaret();
  }, 200);
};

container.addEventListener("input", handleInput);

The handleInput function is called upon any user input. All it does is invoke the format() and setCaret() functions that are wrapped by a simple implementation of the debounce() function. Debounce() reduces the number of times syntax highlighting is fired – which can be rather expensive, depending on how many highlighting rules you apply.

The format() function reads the user input and applies syntax highlighting rules:

const format = () => {
  let text = container.innerText;
  text = text.replace(/"(.*?)"/g, (match) => {
    return `<span style='color:orange'>${match}</span>`;
  });
  container.innerHTML = text;
};

In this simple example, a regular expression detects text surrounded by double quotes. replace() wraps the matched text inside a span element, and some inline CSS colors it orange. innerHTML is used for the HTML syntax to be represented in the DOM.

innerHTML destroys the current selection and sets the caret to the beginning of the editor. This would interrupt the user flow. Therefore, I have to restore the caret to where it was before.

const setCaret = () => {
  let node = container.lastChild;
  if (node) {
    const sel = window.getSelection();
    while(node.nodeType === 1 && node.childNodes.length > 0) {
      node = node.lastChild;
    }
  sel.collapse(node, node.length);
  }
};

setCaret, in the code above, is a simpler version of the actual implementation on JSchallenger. It sets the caret to the end of the editor using Selection.collapse() – which requires the very last text node of the editor. However, once I apply syntax highlighting, the editor might have multiple nodes of different types.

container.lastChild gives me the last child node of the editor – which might be an element node with its own child nodes or a text node. In order to identify the last text node, I apply a while loop, checking if the current node is an element node that has child nodes. If so, I update the current node and repeat the process until I've identified the last text node. Eventually I can apply Selection.collapse() and set the caret to the last character of the last text node.

And that's it! This provides a very basic but functioning code highlighter for a live editor. Here is a rudimentary CodePen demo where you can try it out. But keep in mind that this version is extremely limited for the purpose of this brief tutorial. For the editor to fully work with multiple lines of code, I would have to add some additional features, which I'll leave for another time. You can try the full working version on JSchallenger or contact me on Twitter @kueckelheim and let me know what you think!
 

Now on to this week's tools!

Front-end Frameworks

Spectre.css
A Lightweight, Responsive and Modern CSS Framework that uses flexbox and has lots of components ready for use.

WrapPixel
Angular, React, Vue, and Bootstrap 4 templates and themes, both free and paid.

Arwes
Futuristic sci-fi and cyberpunk-inspired graphical UI framework for web apps. Includes some neat animations and audio.
 
Arwes

Frontendor
A library of reusable HTML blocks and templates to help you build beautiful and professional landing pages quickly and easily by copy-paste.

Brahmos
Supercharged JavaScript library to build user interfaces with React and native templates.

Geist UI
An open source design system for building modern websites and applications. Includes support for React, Vue, and more.

Repluggable
Pluggable micro frontends in React+Redux apps.

Superfine
Now at version 8+. A minimal view layer for building web interfaces. Think Hyperapp without the framework—no state machines, effects, or subscriptions—just the absolute bare minimum.

Electron React Boilerplate
Uses Electron, React, Redux, React Router, webpack, and React Hot Loader for rapid application development.

Toast UI
Now at version 2+. A UI library that includes components, charts, a WYSIWYG editor, and more.

Ionic
The popular cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps hit version 5 early this year.
 
Recommended Reading for Developers:

Testing and Debugging Tools

Tech Productivity
A brief weekly newsletter for tech professionals. Features articles, tips, and tools for improved productivity.   promoted

PWA Inside
A directory of various PWA resources that also includes a manifest generator and a PWA audit.

LT Browser
Mobile view debugging on 25+ device resolutions. Check the mobile view of websites on iOS devices and test both on iPhone and iPad simultaneously.

Uptime360
One-stop monitoring solution. Monitor server, website, blacklist, custom services, and publish status pages. Get notified instantly via Slack, Twitter, Email, SMS, and more.

StackTracey
JavaScript utility to parse call stacks, reads sources with clean and filtered output and sourcemaps.

Spearmint
A simpler way to test your React app. Easily create tests using a UI and refer to the browser, codebase, and docs all in one place. Converts to Jest tests.
 
Spearmint

jscpd
Copy/paste detector for source code that provides the ability to find duplicated blocks implemented on more than 150 programming languages and digital formats of documents.

Check Browser Support
A Chrome or Firefox extension to check browser compatibility for various web platform features by selecting text (e.g. when reading an article or tutorial on a web page).

Instatus
A status page service that's more affordable than other popular alternatives.

Placeholdifier
Chrome extension that turns any website into a live wireframe. Useful for demos, streaming, hiding personal information, visual regression, and more.

Teston
JavaScript test runner similar to tape, but with ES6 module support, simpler sub-test syntax and nice indentation.
 

React Tools

Reactjs-popup
A simple popup component to help you create simple and complex modals, tooltips, and menus for React.

Juliette
Reactive state management powered by RxJS.

react-colorful
A tiny color picker component for modern React apps that's tree-shakable and mobile friendly.
 
react-colorful

react-slick
A React port of the old Slick carousel component.

react-blurify
React component to apply a blur effect to child components.

react-three-flex
Brings the flexbox spec to react-three-fiber, based on Yoga, Facebook's open source layout engine for React Native.

react-async-hook
React hook to handle any async operation in React components.

Draft.js
A Rich text editor framework for React that's customizable and built with Immutable.js

useSound
A React Hook for playing sound effects.

kripod-react-hooks
Essential set of React Hooks for convenient Web API consumption and state management.

Immer
The popular React state management solution is now at version 7+.
 

A Tweet for Thought

Sarah Dayan with some lessons learned from 10 years of software engineering.

A Tweet for Thought
 

Send Me Your Tools!

Made something? Send links via Direct Message on Twitter @WebToolsWeekly (details here). No tutorials or articles, please. If you have any suggestions for improvement or corrections, feel free to reply to this email.
 

Before I Go...

This repo reveals how Sindre Sorhus added CSS/SVG animation to a README on GitHub. Spoiler: It uses an element called "foreignObject" inside an SVG element.

Thanks to everyone for subscribing and reading!

Keep tooling,
Louis
webtoolsweekly.com
@WebToolsWeekly
PayPal.me/WebToolsWeekly