Tag: file

Getting Started With the File System Access API

The File System Access API is a web API that allows read and write access to a user’s local files. It unlocks new capabilities to build powerful web applications, such as text editors or IDEs, image editing tools, improved import/export, all in the frontend. Let’s look into how to get started using this API.

Screenshot of an alert popup asking the user if they want the site to be able to view their files via the File System Access API.

Reading files with the File System Access API

Before diving into the code required to read a file from the user’s system, an important detail to keep in mind is that calling the File System Access API needs to be done by a user gesture, in a secure context. In the following example, we’ll use a click event.

Reading from a single file

Reading data from a file can be done in less than 10 lines of code. Here’s an example code sample:

let fileHandle;   document.querySelector(".pick-file").onclick = async () => {  [fileHandle] = await window.showOpenFilePicker();    const file = await fileHandle.getFile();  const content = await file.text();    return content; };

Let’s imagine we have a button in our HTML with the class .pick-file. When clicking on this button, we launch the file picker by calling window.showOpenFilePicker(), and we store the result from this query in a variable called fileHandle

What we get back from calling showOpenFilePicker() is an array of FileSystemFileHandle objects representing each file we selected. As this example is for a single file, we destructure the result. I’ll show how to select multiple files a bit later.

These objects contain a kind and name property. If you were to use console.log(fileHandle), you would see the following object:

FileSystemFileHandle {kind: 'file', name: 'data.txt'}

The kind can either be file or directory.

On fileHandle, we can then call the getFile() method to get details about our file. Calling this method returns an object with a few properties, including a timestamp of when the file was last modified, the name of the file, its size, and type.

Finally, we can call text() on the file to get its content.

Reading from multiple files

To read from multiple files, we need to pass an options object to showOpenFilePicker().

For example:

let fileHandles; const options = {  multiple: true, };   document.querySelector(".pick-file").onclick = async () => {  fileHandles = await window.showOpenFilePicker(options);    // The rest of the code will be shown below };

By default, the multiple property is set to false. Other options can be used to indicate the types of files that can be selected.

For example, if we only wanted to accept .jpeg files, the options object would include the following:

const options = {  types: [    {      description: "Images",      accept: {        "image/jpeg": ".jpeg",      },    },  ],  excludeAcceptAllOption: true, };

In this example, fileHandles is an array containing multiple files, so getting their content would be done in the following way:

let fileHandles; const options = {  multiple: true, };   document.querySelector(".pick-file").onclick = async () => {  fileHandles = await window.showOpenFilePicker(options);    const allContent = await Promise.all(    fileHandles.map(async (fileHandle) => {      const file = await fileHandle.getFile();      const content = await file.text();      return content;    })  );    console.log(allContent); };

Writing to a file with the File System Access API

The File System Access API also allows you to write content to files. First, let’s look into how to save a new file.

Writing to a new file

Writing to a new file can also be done in a very short amount of code!

document.querySelector(".save-file").onclick = async () => {  const options = {    types: [      {        description: "Test files",        accept: {          "text/plain": [".txt"],        },      },    ],  };    const handle = await window.showSaveFilePicker(options);  const writable = await handle.createWritable();    await writable.write("Hello World");  await writable.close();    return handle; };

If we imagine a second button with the class save-file, on click, we open the file picker with the method showSaveFilePicker() and we pass in an option object containing the type of file to be saved, here a .txt file.

Calling this method will also return a FileSystemFileHandle object like in the first section. On this object, we can call the createWritable() method that will return a FileSystemWritableFileStream object. We can then write some content to this stream with the write() method in which we need to pass the content.

Finally, we need to call the close() method to close the file and finish writing the content to disk.

If you wanted to write some HTML code to a file for example, you would only need to change what’s in the options object to accept "text/html": [".html"]  and pass some HTML content to the write() method.

Editing an existing file

If you’d like to import a file and edit it with the File System Access API,  an example code sample would look like:

let fileHandle;   document.querySelector(".pick-file").onclick = async () => {  [fileHandle] = await window.showOpenFilePicker();    const file = await fileHandle.getFile();  const writable = await fileHandle.createWritable();    await writable.write("This is a new line");  await writable.close(); };

If you’ve been following the rest of this post, you might recognize that we start with the showOpenFilePicker() and getFile() methods to read a file and we then use createWritable(), write() and close() to write to that same file.

If the file you’re importing already has content, this code sample will replace the current content with the new one passed into the write() method.

Additional File System Access API features

Without going into too much detail, the File System Access API also lets you list files in directories and delete files or directories.

Read directories

Reading directories can be done with a tiny bit of code:

document.querySelector(".read-dir").onclick = async () => {  const directoryHandle = await window.showDirectoryPicker();    for await (const entry of directoryHandle.values()) {    console.log(entry.kind, entry.name);  } };

If we add a new button with the class .read-dir, on click, calling the showDirectoryPicker() method will open the file picker and, when selecting a directory on your computer, this code will list the files found in that directory.

Delete files

Deleting a file in a directory can be done with the following code sample:

document.querySelector(".pick-file").onclick = async () => {  const [fileHandle] = await window.showOpenFilePicker();  await fileHandle.remove(); };

If you want to delete a folder, you only need to make a small change to the code sample above:

document.querySelector(".read-dir").onclick = async () => {  const directoryHandle = await window.showDirectoryPicker();  await directoryHandle.remove(); };

Finally, if you want to remove a specific file when selecting a folder, you could write it like this:

// Delete a single file named data.txt in the selected folder document.querySelector(".pick-folder").onclick = async () => {    const directoryHandle = await window.showDirectoryPicker();    await directoryHandle.removeEntry("data.txt"); };

And if you want to remove an entire folder, you would need the following lines:

// Recursively delete the folder named "data" document.querySelector(".pick-folder").onclick = async () => {    const directoryHandle = await window.showDirectoryPicker();    await directoryHandle.removeEntry('data', { recursive: true }); };

File System Access API browser support

At the moment, IE and Firefox don’t seem to be supporting the File System Access API. However, there exists a ponyfill called browser-fs-access.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

Chrome Firefox IE Edge Safari
101 No No 98 TP

Mobile / Tablet

Android Chrome Android Firefox Android iOS Safari
No No No 15.4

Wrapping up

If you’d like to try the File System Access API, check out this live demo text editor built by Google engineers. Otherwise, if you’d like to learn more about this API and all its features, here are some resources:


Getting Started With the File System Access API originally published on CSS-Tricks. You should get the newsletter.

CSS-Tricks

, , , ,

File Scaffolding With Hygen

I read a recent Smashing Magazine post that included a recommendation for Hygen. I just happen to be doing quite a bit of new UI work in a Next.js app and the amount of manual folder/file scaffolding I was doing was getting annoying. So the timing was perfect here.

In this app I’m working on, we’ve agreed as a team that a new component has a structure like this:

/NewComponent   index.js   NewComponent.js   NewComponent.module.scss

For a long time, I’d just manually create the folder and files using the UI options in VS Code.

But that’s slow and boring and prone to error (I can’t tell you how many times I made a file instead of a folder by accident).

What Hygen does is give me a CLI to scaffold all this out. And what I really like is that it’s based on files right in the code base, so that everyone can share them and help update and maintain them as well.

So, to get this going, we’re following the recommended procedure which involves global installation of Hygen:

npm i -g hygen

(This part I’m a little unsure of. Like, since we’re using it on this project now, maybe a local install is smarter so people can’t forget to do it? But will that still let the CLI work? Dunno.)

Once that’s going though, using Hygen is really easy. For example:

hygen editor-component new --name NewExampleComponent

That’s going to go look in the closest folder named _templates for a folder called editor-component and scaffold out everything it finds there. Here’s what those three files look like for me:

Note that the names of the files don’t actually matter that much because, in the front matter of each, you explain where the actual scaffolded file should go and what it should be named. This gives you an opportunity to template the file names as well as the content within them.

The templating looks like Rails ERB to me. So if I pass in --name Cool in the CLI, I get to use <%= name %> in the templates, and there are all sorts of helper functions if you need to uppercase or lowercase it and crap like that.

Run the command, get the files!

Notes

  • I’ve also heard Plop is good, but something about the syntax and approach of Hygen quickly clicked with me.
  • I feel like there should be a hygen jk command that deletes the scaffold you just did because there is always a decent chance you’ll misspell something or otherwise screw it up, and it’s annoying to have to go find those files and delete them.
  • There is also a VS Code Extension which is pretty cool and means you don’t even have to pop over to the terminal to do it or remember the commands, you just kick it right from the Command Palette

CSS-Tricks

, ,
[Top]

You don’t need external assets in an HTML file

A fun exercise from Terence Eden. You can send an HTML file over the wire including anything a website might need without requesting any other files. CSS and JavaScript are easy, because there are <script> and <style> tags. Images and fonts (and pretty much whatever other kind of asset) aren’t too hard because Data URLs exist. See Terence’s post for an extra-tricky final version including .zip files.

Reminds me of a couple of other tricks…

Direct Link to ArticlePermalink


The post You don’t need external assets in an HTML file appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , , ,
[Top]

A Whole Website in a Single HTML File

I can’t stop thinking about this site. It looks like a pretty standard fare; a website with links to different pages. Nothing to write home about except that… the whole website is contained within a single HTML file.

What about clicking the navigation links, you ask? Each link merely shows and hides certain parts of the HTML.

<section id="home">   <!-- home content goes here --> </section> <section id="about">   <!-- about page goes here --> </section>

Each <section> is hidden with CSS:

section { display: none; }

Each link in the main navigation points to an anchor on the page:

<a href="#home">Home</a> <a href="#about">About</a>

And once you click a link, the <section> for that particular link is displayed via:

section:target { display: block; }

See that :target pseudo selector? That’s the magic! Sure, it’s been around for years, but this is a clever way to use it for sure. Most times, it’s used to highlight the anchor on the page once an anchor link to it has been clicked. That’s a handy way to help the user know where they’ve just jumped to.

Anyway, using :target like this is super smart stuff! It ends up looking like just a regular website when you click around:

Direct Link to ArticlePermalink


The post A Whole Website in a Single HTML File appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , ,
[Top]

React Single File Components Are Here

Shawn Wang is talking about RedwoodJS here:

…  it is the first time React components are being expressed in a single file format with explicit conventions.

Which is the RedwoodJS idea of Cells. To me, it feels like a slightly cleaner version of how Apollo wants you to do it with useQuery. Shawn makes that same connection and I know RedwoodJS uses Apollo, so I’m thinking it’s some nice semantic sugar.

There is a lot of cool stuff going on in RedwoodJS. “A highly opinionated stack” if its helpful to think of it that way, but Tom made clear in our last episode of ShopTalk that it’s not like Rails. Not that Rails is bad (it isn’t), but that this new world can do things in new and better ways that make for long-term healthy software.

The post React Single File Components Are Here appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Weekly Platform News: Contrast Ratio Range, replaceAll Method, Native File System API

In this week’s roundup: Firefox’s new contrast checker, a simpler way to lasso substrings in a string, and a new experimental API that will let apps fiddle with a user’s local files.

Firefox shows the contrast ratio range for text on a multicolored background

According to Success Criterion 1.4.3 of the Web Content Accessibility Guidelines (WCAG), text should have a contrast ratio of at least 4.5. (A lower contrast ratio is acceptable only if the text is 24px or larger.)

If the background of the text is not a solid color but a color gradient or photograph, you can use the special element picker in Firefox’s Accessibility panel to get a range of contrast ratios based on the element’s actual background.

(via Šime Vidas)

Replacing all instances of a substring in a string

The new JavaScript replaceAll method makes it easier to replace all instances of a substring in a string without having to convert the substring to a regex first, which is “hard to get right since JavaScript doesn’t offer a built-in mechanism to escape regular expression patterns.”

// BEFORE str = str.replace(/foo/g, "bar");  // AFTER str = str.replaceAll("foo", "bar");

This new string method has not yet shipped in browsers, but you can start using it today via Babel (since it’s automatically polyfilled by @babel/preset-env).

(via Mathias Bynens)

Try out the Native File System API in Chrome

The Native File System API, which is experimentally supported in Chrome, allows web apps to read or save changes directly to local files on the person’s computer. The app is granted permission to view and edit files in a specific folder via two separate prompts.

You can try out this new feature by visiting labs.vaadin.com in Chrome on desktop.

(via Thomas Steiner)

More news…

sunday-issue-18.png

Read more news in my weekly newsletter for web developers. Pledge as little as $ 2 per month to get the latest news from me via email every Monday.

More News →

The post Weekly Platform News: Contrast Ratio Range, replaceAll Method, Native File System API appeared first on CSS-Tricks.

CSS-Tricks

, , , , , , , , , ,
[Top]

It’s pretty cool how Netlify CMS works with any flat file site generator

Little confession here: when I first saw Netlify CMS at a glance, I thought: cool, maybe I’ll try that someday when I’m exploring CMSs for a new project. Then as I looked at it with fresh eyes: I can already use this! It’s a true CMS in that it adds a content management UI on top of any static site generator that works from flat files! Think of how you might build a site from markdown files with Gatsby, Jekyll, Hugo, Middleman, etc. You can create and edit Markdown files and the site’s build process runs and the site is created.

Netlify CMS gives you (or anyone you set it up for) a way to create/edit those Markdown files without having to use a code editor or know about Pull Requests on GitHub or anything. It’s a little in-browser app that gives you a UI and does the file manipulation and Git stuff behind the scenes.

Here’s an example.

Our conferences website is a perfect site to build with a static site generator.

It’s on GitHub, so it’s open to Pull Requests, and each conference is a Markdown file.

That’s pretty cool already. The community has contributed 77 Pull Requests already really fleshing out the content of the site, and the design, accessibility, and features as well!

I used 11ty to build the site, which works great with building out those Markdown files into a site, using Nunjucks templates. Very satisfying combo, I found, after a slight mostly configuration-related learning curve.

Enter Netlify CMS.

But as comfortable as you or I might be with a quick code edit and Pull Request, not everybody is. And even I have to agree that going to a URL quick, editing some copy in input fields, and clicking a save button is the easiest possible way to manage content.

That CMS UI is exactly what Netlify CMS gives you. Wanna see the entire commit for adding Netlify CMS?

It’s two files! That still kinda blows my mind. It’s a little SPA React app that’s entirely configurable with one file.

Cutting to the chase here, once it is installed, I now have a totally customized UI for editing the conferences on the site available right on the production site.

Netlify CMS doesn’t do anything forceful or weird, like attempt to edit the HTML on the production site directly. It works right into the workflow in the same exact way that you would if you were editing files in a code editor and committing in Git.

Auth & Git

You use Netlify CMS on your production site, which means you need authentication so that just you (and the people you want) have access to it. Netlify Identity makes that a snap. You just flip it on from your Netlify settings and it works.

I activated GitHub Auth so I could make logging in one-click for me.

The Git magic happens through a technology called Git Gateway. You don’t have to understand it (I don’t really), you just enable it in Netlify as part of Netlify Identity, and it forms the connection between your site and the Git repository.

Now when you create/edit content, actual Markdown files are created and edited (and whatever else is involved, like images!) and the change happens right in the Git repository.


I made this the footer of the site cause heck yeah.

The post It’s pretty cool how Netlify CMS works with any flat file site generator appeared first on CSS-Tricks.

CSS-Tricks

, , , , , , , ,
[Top]

When’s the last time you SFTP’d (or the like) into a server and changed a file directly?

In the grand tradition of every single poll question I’ve ever posted, the poll below has a has a fundamental flaw. In this case, there is no option between “In the last month” and “Never” but, alas, the results are interesting:

What I was trying to get at with this poll is how many people do and don’t do any sort of editing of production files directly and instead work locally. I don’t think I need to launch a major investigation to know that it’s most people and more than in the past.

Most workflows these days have us working locally and pushing new and updated files through a version control system, and even through systems beyond that, perhaps continuous integration processes, testing processes, actions, deployment — it’s big world of DevOps out there! Rarely do we skip the line and dip our fingers into production servers and make live manipulations. Cowboy coding, they sometimes call it.

But just because you don’t generally code that way doesn’t mean you never do it, which is another flaw of this poll. I know DevOps nerds who are constantly SSH-ing into servers to manipulate configuration files. I personally still hop into Coda and will directly SFTP into servers sometimes to edit .htaccess files, which are sometimes on my production sites and dev sites and that I generally .gitignore.

Anyways, I think this is a fun thing to talk about, so feel free to have at it in the comments. I’d love to hear to what degree you cowboy code. Still do it all the time and love it? Do you do it because you haven’t learned another way or that’s how your workplace demands? Do you have a personal philosophy about it? Let the rodeo begin. 🤠

The post When’s the last time you SFTP’d (or the like) into a server and changed a file directly? appeared first on CSS-Tricks.

CSS-Tricks

, , , , , , , , ,
[Top]