20200714のNode.jsに関する記事は5件です。

簡単レシート印刷 receiptline で文字装飾してみた

日本発のオープンソース receiptline でレシート印刷に少しずつトライしています。
まだレシートプリンターがないので、前回セットアップした開発ツールを引き続き使います。
今回は文字装飾です。

01.png

文字装飾の種類

文字装飾は 4 種類。
アイコンは左から、アンダーライン、強調、白黒反転、拡大です。
クリックすると文字装飾記号を挿入します。

02.png

キーボードで文字装飾記号を直接入力しても OK。
_ はアンダーライン、" は強調、` は白黒反転、^ は拡大です。

装飾の開始

文字装飾記号を挿入すると、それ以降の文字が装飾されます。

ReceiptLine
_hello, world!
"hello, world!
`hello, world!
^hello, world!

03.png

装飾の範囲

同じ文字装飾記号で囲むと、その範囲にある文字が装飾されます。

ReceiptLine
_hello_, world!
"hello", world!
`hello`, world!
^hello^, world!

04.png

装飾の組み合わせ

文字装飾を組み合わせることができます。
範囲を入れ子にしなくても大丈夫。

ReceiptLine
"`hello", world!`

05.png

拡大いろいろ

拡大文字装飾記号を重ねると、さらに大きな文字になります。

ReceiptLine
hello
^hello
^^hello
^^^hello
^^^^hello
^^^^^hello
^^^^^^hello
^^^^^^^hello

06.png

装飾記号の出力

文字装飾記号の前に \ を付けると、普通の文字になります。

ReceiptLine
\"hello, world!\"

07.png

水平線と用紙カット

普通の文字装飾とは少し違うものもあります。
アイコンは左が水平線、右が用紙カットです。クリックすると記号を挿入します。

08.png

- は水平線、= は用紙カットです。キーボードからの直接入力もできます。
これらの特殊記号は、1 行に他の文字と混在しないときに有効です。

ReceiptLine
hello, world!
---
hello, world!
===
hello, world!

09.png

次回は位置揃えを試してみようと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ESLint 7.4.0

v7.3.0 | 次 (2020-07-18 JST)

ESLint 7.4.0 がリリースされました。小さな機能追加とバグ修正が含まれています。

  • Optional Chaining 構文対応はこちらで進行中です。もうしばらくお待ちください。
  • 前回発生していたリグレッションは Revert されました。

質問やバグ報告等ありましたら、お気軽にこちらまでお寄せください。

? 日本語 Issue 管理リポジトリ
? 日本語サポート チャット (招待リンク)
? 本家リポジトリ
? 本家サポート チャット (招待リンク)


[PR] ESLint は開発リソースを確保するための寄付を募っています。
応援してくださると嬉しいです。


✨ 本体への機能追加

特になし

? 新しいルール

id-denylist

? #13408

既存の id-blacklistid-denylist に名称変更されました。
id-blacklist も、id-denylist の別名として、引き続き利用できます。

? オプションが追加されたルール

camelcase ignoreGlobals

? #12782

グローバル変数を無視するオプションが追加されました。

/*eslint camelcase: [error, { ignoreGlobals: true }] */
/*globals fizz_buzz */

//✔ GOOD
fizz_buzz = 0

//✖ BAD
const foo_bar = 0

Open Online Demo

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

propsの引き渡し

express+node.js+next.js+reactのpropsの引き渡しの流れ

  1. routes/**.jsxのrender内で変数を定義
  2. pages/app.jsxでpropsとして変数を受け取りpages/**.jsxに渡す
  3. pages/**.jsxでさらにpropsとして受け取る

1->2はnext.jsの機能らしい

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React + TypeScript 環境構築 + ビルド環境を Flavor で切り替える (not create-react-app)

はじめに

この記事は React + TypeScript な環境を作成し、Flavor を設定してビルド環境( Development, Staging, Production )を切り替えられるような Project を作成することを目的としています。

React + TypeScript 環境の構築

初期設定

サックっと初期設定してしまいましょう。

$ mkdir react-flavor-example
$ cd react-flavor-example
$ npm init

色々聞かれるので、適当に質問に答えましょう。

package name: (app) react-flavor-example
version: (1.0.0)
description:
entry point: (main.tsx) webpack.config.js
test command:
git repository:
keywords:
author: yukitaka13-1110
license: (ISC)
About to write to /app/package.json:

Dependency の追加

React 系

$ npm i -D react react-dom @types/react @types/react-dom

Webpack 系

$ npm i -D webpack webpack-cli webpack-dev-server html-webpack-plugin

TypeScript 系

$ npm i -D typescript ts-loader

tsconfig.json の作成

tsconfig.json
{
  "compilerOptions": {
    "sourceMap": true,
    "module": "commonjs",
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "experimentalDecorators": true,
    "target": "es5",
    "jsx": "react",
    "lib": [
      "dom",
      "es6"
    ]
  },
  "include": [
    "src"
  ],
  "compileOnSave": true
}

webpack.config.js の作成

webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'development',

  entry: './src/main.tsx',
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
    }),
  ],
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
      },
    ],
  },
  resolve: {
    extensions: [
      '.ts', '.js', 'tsx',
    ],
  },
};

index.html の作成

public/ 以下に index.html を作成します。

public/index.html
<html lang="ja">
  <body>
    <div id="root" />
  </body>
</html>

main.tsx の作成

src/ 以下に main.tsx を作成します。

src/main.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";

const App: React.FC = () => {
  return <div>React Flavor Example</div>
};

ReactDOM.render(<App />, document.getElementById("root"));

この時点でディレクトリ構造が以下のようになっていればOKです。

$ tree ./ -L 2

./
├── node_modules
├── package-lock.json
├── package.json
├── public
│   └── index.html
├── src
│   └── main.tsx
├── tsconfig.json
└── webpack.config.js

package.jsonscripts にコマンドを追加します。

package.json
{
  ...
  "scripts": {
    "start": "webpack-dev-server",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  ...
}

npm run start で起動して http://localhost:8080/ へアクセスして React Flavor Example という文字が表示されることを確認

スクリーンショット 2020-07-14 01.19.36.png

Flavor の設定

ここからが本題です。
アプリで利用する環境変数を切り替えたいということは良くあることだと思います。
node.js では process.env.NODE_ENV という環境変数を利用することでアプリで利用する環境変数を切り替えることができるようです。
しかし、process.env.NODE_ENVstaging を受け取ることができません。型定義を見る感じは受け取れそうですが、どうやらdevelopment | production | test 以外は受け付けないようにないっているみたい...。(良く分かっていない)

@types/node
interface ProcessEnv {
    [key: string]: string | undefined;
}

そもそも型定義も貧弱なのでそこも含めて解決します。

process.env の型を上書きする

process.env の型を上書きするには、プロジェクト内のどこかに global.d.ts ファイルを作成し、以下のように書くことで可能です。

src/types/global/global.d.ts
/// <reference types="node" />

declare namespace NodeJS {
  interface ProcessEnv {
    readonly NODE_ENV: 'development' | 'production' | 'test';
    readonly FLAVOR: 'development' | 'staging' | 'production';
  }
}

NODE_ENV は触っちゃいけない気がしたので以下のように FLAVOR を生やしてみました。

その後、package.jsonFLAVOR を渡す scripts を追加します。

package.json
{
  "scripts": {
    "start": "webpack-dev-server",
+   "dev": "FLAVOR=\"development\" webpack-dev-server",
+   "stg": "FLAVOR=\"staging\" webpack-dev-server",
+   "prod": "FLAVOR=\"production\" webpack-dev-server",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
}

渡しただけではアプリ側では受け取れないので、webpack.config.js で工夫します。

webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
+ const webpack = require('webpack');
+ const flavor = process.env.FLAVOR || 'development';

module.exports = {
  mode: 'development',

  entry: './src/main.tsx',
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
    }),
+   new webpack.DefinePlugin({
+     'process.env.FLAVOR': JSON.stringify(flavor),
+   })
  ],
}

main.tsxconsole.log() を追加してみましょう。
先程、型定義を上書きしたので補完が効くようになっています。

スクリーンショット 2020-07-14 01.56.01.png

試しに npm run stg を実行してみましょう。
ちゃんと値を受け取れています。

スクリーンショット 2020-07-14 01.57.50.png

後は適当に環境毎に変数を定義して process.env.FLAVOR を使って分岐するだけです。
例えば以下のような config ディレクトリを用意しておけば良いでしょう。

./src/config
├── development
│   └── index.ts
├── index.ts
├── production
│   └── index.ts
└── staging
    └── index.ts
staging/index.ts
import { EnvVariables } from '../';

const stgVariables: EnvVariables = {
  HOGE: 'STAGING_HOGE',
  FUGA: 'STAGING_FUGA',
};

export default stgVariables;
index.ts
import devVariables from './development';
import stgVariables from './staging';
import prodVariables from './production';

export type EnvVariables = {
  HOGE: string;
  FUGA: string;
};

const envVariables = (): EnvVariables => {
  if (process.env.FLAVOR === 'production') {
    return prodVariables;
  }
  if (process.env.FLAVOR === 'staging') {
    return stgVariables;
  }
  return devVariables;
};

export default envVariables();
src/main.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import envVariables from './config' // Add import;

const App: React.FC = () => {
  return (
    <div>
      <div>React Flavor Example</div>
      <div>{envVariables.HOGE}</div>
      <div>{envVariables.FUGA}</div>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));

npm run stg を実行して http://localhost:8080/ にアクセスします。

スクリーンショット 2020-07-14 02.22.48.png

ちゃんと値を表示することができました。

終わりに

今回使用したコードはこちらに載せています。
https://github.com/yukitaka13-1110/react-flavor-example

現在、QUANDO では iOS, Android, Flutter エンジニア募集中です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

<JavaScript>特定の文字列で区切られたファイル名をそのファイル名の一部で一括変換するクイズ

背景

やりたいこと

  • フォルダの中にabc_test_ok_1_this.csv・・・abc_test_ok_100_this.csvのファイルが入っている
  • これらを1.csv・・・100.csvにリネームしたい
  • ということだと思う(斜め読みしたから違うかも)
  • これらをコマンドラインでワンライナーで実現するというもの

環境

node -v
# v14.5.0

事前準備

  • 元記事はabc_test_ok_1_this.csv・・・abc_test_ok_100_this.csvのファイルを用意するところからワンライナーでやってるのでそこから
node -e "const fs=require('fs');[...Array(100).keys()].forEach(i=>fs.writeFile('abc_test_ok_'+(i+1)+'_this.csv','',()=>{}));"
  • nodeコマンドはnode main.jsのようにしてファイルを実行できるが、node -e "console.log('Hello')"のように-eオプションをつけるとその後をEvalするのでファイルに書かなくても直接実行できる
  • ちゃんと改行するとこんな感じ
const fs = require('fs');

[...Array(100).keys()].forEach(i => {
  fs.writeFile(`abc_test_ok_${i + 1}_this.csv`, '', () => {});
});
  • [...Array(100).keys()]で要素数100個の配列を作っています
    • .kyes()としてるので配列の各要素には0〜99の値が格納されます
    • [0, 1, 2, ... 98, 99]といった具合
  • これをforEachしてるので100回ループが回ってます
  • ファイルの作成にはfs.writeFile('ファイル名', 'ファイルの内容', callback)を使っています
    • ファイル名はお題の名前にしてindexを埋め込んでいる
    • ファイルの中身は指定がなかったので空っぽに
    • コールバックはとりあえず今回はいらないので空の関数
  • という感じで実行するとabc_test_ok_1_this.csv・・・abc_test_ok_100_this.csvが作成されました

ファイルのリネーム

  • ここが本題でしょうか
  • フォルダの中にあるabc_test_ok_1_this.csv・・・abc_test_ok_100_this.csvのファイルを1.csv・・・100.csvにリネームします
node -e "const fs=require('fs');fs.readdir(__dirname,(error,files)=>{files.forEach(file=>{fs.rename(file,file.match(/abc_test_ok_(.*)_this.csv/)[1]+'.csv',() => {},);});});"
  • さっきと同じくnodeコマンドの-eオプションを使ってワンライナーで実現しています
  • 改行するとこんな感じ
const fs = require('fs');

fs.readdir(__dirname, (error, files) => {
  files.forEach(file => {
    fs.rename(file, file.match(/abc_test_ok_(.*)_this.csv/)[1] + '.csv', () => {});
  });
});
  • fs.readdir('ディレクトリ', callback)を使ってディレクトリの中のファイル一覧を取得しています
    • 第1引数はカレントディレクトリでいいので__dirnameを定義
    • 第2引数はファイル名の一覧を処理する関数を定義
  • filesにファイル名の一覧が入っているのでfiles.forEach(file => { ... }でループを回しています
  • fs.rename('変更前のファイル名', '変更後のファイル名', callback)を使ってリネームしています
    • 変更前のファイルはループで回ってくるfile
    • 変更後のファイル名は正規表現で必要な部分を引き抜いています
    • callbackは今回は不要なので空の関数
  • これでフォルダの中にあるabc_test_ok_1_this.csv・・・abc_test_ok_100_this.csvのファイルを1.csv・・・100.csvにリネームできました
    • 余計なファイルがあったときの処理とかはいったん無視しました

終わりに

  • ちょっとしたスクリプトを書くのは息抜きの暇つぶしにいいですね。
  • Nodeでファイルの読み書きなんてほとんどやったことないのでググりながらやりました。もっとかっこいい書き方あるかも。
  • 次は誰かPythonとかRubyとかでお願いします。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む