The final result

The source code

background

origin



According to insiders, the back-end mail sending service is the back-end to send a.htmlFile (back-end written) to implement, due to different mail platforms, the parsing of this HTML is not the same, the style often does not fit the situation.

All right! After the end of the pot will not live, change the style compatible things naturally fell to the front head head body, front head head which have this empty? Such a big pot and naturally fell on the “front cut figure son” body.

A dead heart

The first thing to do with HTML email is to write all your CSS inline!

As with normal HTML page development, HTML mail still needs CSS. HTML mail does not support external style files. The head tag is most likely to be deleted, so do not try to write style tags inside the head tag. Is it safe to write a style tag inside the body? Is not! Typically, Gmail removes all style tags from HTML messages, which means that the CSS in the inline style attribute is the only reliable style information.



Boy, there’s more than 100 of themhtmlFile, change my direct feather ascend fairy ~, according to a file 8min (not including running script test time), this wave of operation, really physical work.

Don’t do manual work

Without manual labor, Cheetoozi has dignity. So on second thought, since more than 100 files to do the same thing, that first a CLI command line to batch processing is not finished? Objective: To execute HTML2Email Gen to automatically convert HTML to the style suitable for the mail platform

scenario

Based on HTML mail, let’s take a look at a general scenario for CSS inline styles

  • Send E-mail
  • Embed HTML in third-party web sites
  • Copy edited articles from other editors and post them to we-media such as wechat and Toutiao

Using inline styles in the above scenarios is much more compatible and allows you to keep the original style intact and load faster. Current solutions include Juice and Inline-CSS (thanks open source!).

CLI Project Construction

Step1: initialize the project

Create an empty project (EOS-CLI) and initialize it using YARN Init

Yarn init // Just press enter, change everything else laterCopy the code

Support TypeScript&Rollup packaging

It is highly recommended to use TypeScript for strong type checking and very friendly hints. More detailed configuration of the article has written some.

// install yarn add tslib typescript -d // generate ts configuration files, tsconfig.json can be used to configure compiled JS versions, tslint checks, etc. NPX TSC --init // install rollup, Create the rollup.config.js configuration file yarn add rollup -dCopy the code

Bin Execution script

Node.js has built-in support for command-line operations, which is a mapping of command names to local file names. At installation time, NPM will use symbolic links to link these files to {{prefix}}/bin if it is a global installation or./node_modules/.bin/ if it is a local installation. For a global installation, we can execute this file on the command line. For a local installation, we can execute this file on the command line in the current project directory.

"bin": {
	"html2email": "bin/index.js"
},
Copy the code

Note: the index.js file must have this #! /usr/bin/env node specifies that the current script is parsed by Node.js

#! /usr/bin/env node/ /.. /lib/ bundle.js.'.. /lib/bundle.cjs.js') 
Copy the code

The directory structure

├ ─ ─ bin │ └ ─ ─ index. The js / / bin executable ├ ─ ─ lib ├ ─ ─... ├─ SRC ├─ ├─ ├.txt // ├─ index.ts // Main process import File ├─.babelrc // Babel Config file ├─ package.json ├─ rollup.config.js // Rollup Config File ├─ Json // Ts Configuration File ├─ yarn.lock ├─ readme.mdCopy the code

Step2: HTML2email command to use

Start the project

// Run yarn build yarn build // package.json scripts(-w monitors file changes and automatically packages any changes)."scripts": {
	"build": "rollup -c -w"
},
Copy the code

The global

Execute in the current directorynpm link/ yarn linkTo link the HTML2email command to the global environment.

After I’ve done these two steps,html2emailIt can be used normally

The implementation process

After creating a new command line project, it’s time to heap code into the project in two steps

  • Process the command line that identifies user input
  • Execute the HTML to HTML mail method (only converting styles to inline styles here!!)

Html2email command line processing

Use CAC to process the command line, rich and powerful, CAC NPM

Command And Conquer is a JavaScript library for building CLI apps

import cac from 'cac'
const cli = cac()

// When the user enters html2email only, other commands are displayed as friendly prompts
cli.command(' ').action(() = > {
  cli.outputHelp()
})
// html2email gen is executed when the option parameter is passed to control the flow
cli
  .command('gen'.'Generate target resources')
  .option('-k, --keepFolderStructure'.'keep original folder structure')
  .allowUnknownOptions()
  .action(async (flags: Partial<CliOptions>) => {
    const config = await getConfig(flags)
    genHtmlEmail(config as CliOptions)
  })
Copy the code

Read external HTML2email configuration

export type CliOptions = {
  include: string | string[]
  exclude: string | string[]
  outDir: string
  title: string
  keepFolderStructure: boolean
}
Copy the code

CliOptions has 5 configuration items, although can through the command line to override the default input values, here I can directly read the external package. Json, html2email. Json file to obtain the current configuration items. It is worth mentioning that joycon is really good, hahaha ~ Joycon NPM

const JoyCon = require('joycon')
const joycon = new JoyCon({
  packageKey: 'html2email'
})

const { path, data } = await joycon.load([
  'package.json'.'html2email.json'
])
// console.log('path, data', path, data)
path: /Users/Autumn/package.json
data: { exclude: [ 'node_modules']}Copy the code

GenHtmlEmail implementation

The goal is to convert all the.html files in the current directory to CSS inline.html files, which can be broken down into the following steps.

  • Go through all the files in the directory and find.htmlDocuments have tofilesAn array of
  • traversefiles
    • Fs reads the source file
    • inline-cssConvert to email supported HTML CSS inline style
    • Output the final converted file

Obtaining the file pathfiles

Can lie flat lie flat 🐶, here using the method provided by fast-Glob

This package provides methods for traversing the file system and returning pathnames

The output will yield the following array

Iterate through processing files and output

So let’s go straight to the code.

export default async (config: CliOptions) => {
  let {
    include,
    exclude,
    outDir,
    keepFolderStructure
  } = config
  if (typeof include === 'string') include = [include]
  if (typeof exclude === 'string') exclude = [exclude]
  const files = await fg(include.concat(exclude.map(p= > `!${p}`)))
  console.log('files', files)
  return files.map(async (p: string) => {
    // fs reads the source file
    const abs = path.resolve(p)
    const source = await fs.readFile(abs, 'utf-8')
    // Convert to HTML CSS inline format supported by email
    try {
      const parserHtml = await inlineCss(source, {
        url: 'filePath'
      })
      const compName = path.basename(abs)

      // fs outputs the final file
      let targetDir = outDir? path.resolve(
        outDir
      ) : path.dirname(abs)

      let targetFile = compName
      const folderStructureMiddlePath: string = keepFolderStructure
        ? getGlobPatternMatchPath(include as string[], path.dirname(p))
        : ' '
      const target = path.resolve(
        targetDir,
        folderStructureMiddlePath,
        targetFile
      )
      await fs.ensureDir(path.resolve(targetDir, folderStructureMiddlePath))
      await fs.writeFile(target, parserHtml)
      return {
        compName,
        content: parserHtml
      }
    } catch (error) {
      console.log('error---- ', error)
    }
  })
}
Copy the code

In addition, the getGlobPatternMatchPath method implementation is quite interesting, interested friends can look at the source code.

The end of the

Through the CLI command line to batch processing back-end students before more than 100 HTML mail files, instantaneous processing completed, work to play ⛹ to ~~~

The above 👆🏻 seems to be a powerful operation, but in fact, it only implements the CSS inline style. Toemail still needs to be written according to the CSS compatibility of the major email platforms.The Ultimate Guide to CSS.

conclusion

After reading some articles of huang Yihuang teacher, after such a toss feeling quite deep, according to my former leng Tou qing, certainly is a direct document modification (too vegetables ~~)…. Now there is a kind of thinking that is “free hands, lazy can be lazy”, otherwise physical work really can not stand; In particular, restore the UI design draft, at the beginning to set a good component specification with the UI designer, can be extracted into components on the smoke, for later save a lot of things, just have time for other things!

Look at the harvest, like comment support ~ source code

Put a tag on the back end in case it helps them. Hahaha

reference

HTML Mail compatibility Issues and Solutions CSS-Inline Vuese is a solution for converting CSS to inline styles