sassでmin関数使おうとしてIncompatible unitsエラーが出た場合はクオートで回避する

概要

sassで「プレーンCSSのmin関数」を使う場合はクオートを使う。
「sassのmin関数」とは別物だと分からせろ。

min関数を使って幅のあるpaddingを設定したかったが…

プレーンcssの方のmin関数を使って
paddingを「表示幅の2%。ただし最大30px。」にしたかった。

具体的に言うと

幅 300pxの画面で見るとpadding:  6pxになる
幅 600pxの画面で見るとpadding: 12pxになる
幅1000pxの画面で見るとpadding: 20pxになる
幅1200pxの画面で見るとpadding: 24pxになる
幅1500pxの画面で見るとpadding: 30pxになる
幅1600pxの画面で見るとpadding: 30pxになる
幅2000pxの画面で見るとpadding: 30pxになる

とやりたかったので以下の記述

padding: min(2vw,30px);

が、

sassとプレーンcssでmin関数がかぶってしまったな…

「Error: Incompatible units: ‘px’ and ‘vw’.」と
コンパイルエラー発生。
「sassのmin関数は単位を揃えろ」と怒られた。
もちろん「プレーンcssのmin」は単位を揃える必要は無い。

調べた所、以下の内容を発見。

Sass: Special Functions
https://sass-lang.com/documentation/syntax/special-functions#min-and-max

以下、意訳。

  • 従来のsassと新規のプレーンcssでmin関数の名前がかぶってしまった。うまく使い分けて欲しい。
  • 該当部分を含むのが「css」ファイルであればエラーは起こらない
  • Dart Sassの場合は変数や関数を使わなければプレーンcssのminとして解釈する
  • クオートつけてunquoteする事で回避できる

先程の記述だと見分けがつかない。ということか。

クオート使って回避できた。

padding: unquote("min(2vw,30px)");

で解決。

padding: min(2vw,30px);

ちゃんととコンパイルされていた。

それならclamp()で良いのでは?

padding: clamp(6px,2vw,30px);

通常2vwで最小6px、最大30pxと設定できる。
こちらなら衝突は起きないのでそのまま使える。

…何をムキになっていたのでしょうね。
道理でどこ探しても話題になっていないわけだ。

ファイル監視時のエラー「File to read not found or unreadable」はsublime textの設定で改善できるかもしれない

概要

テキストエディタ「sublime text」はファイル保存時のロック開放が遅い時があり、更新を監視していると「ファイルが見つからない、または使えないエラー」が出る事がある。
代替ファイルに一旦保存するオプション「atomic_save」を適用して解決した。

エラー「File to read not found or unreadable」が出たり出なかったり

SCSSをレンダリングするためにnode.jsを用いてSCSSファイルを監視していた。
更新すると時々「File to read not found or unreadable」エラーが出たり出なかったりした。

sublime textが原因だった

メモ帳では出なかったので、
使用しているエディタ「sublime text」がファイルをロックしているのだろうと推測。

エラーが起きた場合に再帰的にレンダリングを呼び出し、成功するまで無限ループさせる事でとりあえず目的は達成できた。
時々エラーは出続けたが。

「atomic_save: true」で解決

sublime textに代替ファイルに一旦保存するオプション「atomic_save」がある事を知った。

設定方法は
「基本設定」→「基本設定-ユーザー」
「{}」の中に
“atomic_save”: true,
を追加する。だけ。

備考:力技の成功するまでループ

一応再起ループの部分だけ掲載。
参考にならんと思うけど。

// index.js(npm-scriptsで実行しているファイル)

const fs       = require('fs');
const n_sass   = require("node-sass");

// SCSSファイルの更新を検知すると呼ばれる
function sass_flow(){
  return Promise.resolve()
  .then(()=>{
    console.log("render start");
    return sass_render("./css/style.scss","style.css");
  })
  .then((result)=>{
    console.log("writeFile start");
    return write_file("./style.css","./style.css.map",result);
  })
  .then(()=>{
    console.log("browser reload");
    bs.reload
  })
  // エラーをキャッチしたら自分を呼び直す
  .catch((err)=>{
    console.log("sass_flow de error catch!! 再帰呼び出し!!");
    console.log(err);
    sass_flow(); 
  });
}


const sass_render = (input,output)=>{
  return new Promise(function(resolve,reject){
    n_sass.render({
      file: input,
      outputStyle: 'expanded',
      sourceMap: true,
      outFile: output
    },
    function(error,result){
      if(error){
        // console.log(error);
        reject(error);
      }else{
        console.log("render success");
        resolve(result);
      }
    });
  });
}

//cssとmapを書き込んだらresolveを返す
const write_file = function(file,map,renderResult){
  let path_css = file;
  let path_map = map;

  return new Promise(function(big_resolve,big_reject){
    Promise.resolve()
    .then(function(){
      write_the_file(path_css, renderResult.css);
    })
    .then(function(){
      write_the_file(path_map, renderResult.map.toString());
    })
    .then(function(){
      big_resolve();
    })
    .catch(function(err){
      //error処理
      // console.log(err);
      big_reject(err);
    });
  });
}

function write_the_file(path,str){
  return new Promise(function(res,rej){
    fs.writeFile(path, str, function(err){
      if(!err){
        res();
      }else{
        rej(err);
      }
    });
  });
}

スプレッドシートの更新をLINEに通知する

概要

複数拠点感で共用している進捗管理のgoogleスプレッドシートが更新通知が欲しい。
LINEが無料だったので導入した。簡単だった。

手順

LINEアカウントを準備

LINE notifyからトークンを取得する。
・メールアドレスの登録が必要。
・PCからアクセスする必要がある。

Google Apps Script

対象のスプレッドシートにスクリプトを書く

📝LINE notifyを呼ぶスクリプト例

function send_line(){
  var token = "トークン文字列"; 
  var okuru_text = "LINEで通知する文章\nで改行もできる";
  var options  = {
     "method"  : "post",
     "payload" : "message=" + okuru_text,
     "headers" : {"Authorization" : "Bearer "+ token}
  };
  UrlFetchApp.fetch("https://notify-api.line.me/api/notify",options);
}

本件で試したらUrlFetchApp.fetch()に文句言われた。
マニフェスト ファイルで「script.external_request」を許可したら解決した。

📝マニフェストファイル

{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "oauthScopes": [
      "https://www.googleapis.com/auth/script.external_request"
  ]
}

注意事項

スクリプトを消してもトークンは生き続けるので注意。
使わなくなったらLINE notifyから削除しよう。

firefoxのスクラッチパッドが無くなる

概要

firefoxが備えているjavascriptをテストする機能「スクラッチパッド」が廃止される。
代わりにコンソールを使いましょうね。
ってmozillaが言ってた。

解決手順

スクラッチパッドに見慣れない黄色い帯が。
“scratchpad will be disabled in a future release.””
意訳:スクラッチパッドは近いうちに無くなるぜ。詳しくは以下のリンクに。
Deprecated tools – Firefox Developer Tools | MDN

意訳:
ScratchpadはFirefox 70で非推奨になるので、
代わりにwebコンソールを使え。
複数行のコードを入力したい場合は「ctrl + enter」を押せ。
あるいは文脈によってはenterでも「改行」として解釈してやる。

とのことだけど、「ctrl + enter」だと実行されちゃう。
「shift + enter」の間違いっぽい。
上記リンク先内にサンプルコードがあったので参考に。 エンター押すたびに返り値が表示されるけど
実行前に定義した定義した変数や関数もちゃんと残っているので安心。

切り替えていこう。

windows機でnpm-scriptでsublime-textとgulpを同時に起動したい

概要

windows機でnpm-scriptで「エディタの起動」と「gulp」を1コマンドで行いたい。
環境変数PATHと「|(パイプ)」を使うことで解決できた。

解決方法と注意事項

//package.json
"scripts": {
    "gulp": "npm run gulp",
    "sublime": "sublime_text .",
    "start": "npm run sublime | gulp"
},
作業開始時に対象フォルダで「npm run start」。
エディタが開き、gulpが起動する。
ズボラばんざい。

注意事項

  • 「|(パイプ)」は本来ならば出力の受け渡しに使うが、
    ここでは左辺を終了させるためだけに使っている。
  • 環境変数PATHにsublime_Textの実行ファイルを登録しておく必要がある。
  • 汎用性に欠いたpackage.jsonを作るのはどうかと思う

別案

同時起動の部分だけに関して言うならば
npm-run-all – npm

このパッケージインストールした方が早い。
並列と直列の両対応らしい。試してないけど。

やりたかった事

やりたかった事は
開始コマンドを1つ入力すると
  1. エディタがフォルダ(プロジェクト)を開き、
  2. gulpが起動する
というシンプルな内容。
gulp単品での起動と使い分けができるようにする。
エディタはsublime_textを使用。

半角スペースがエスケープできない

まず試してみた。
エディタのフルパスをそのままぺたり。
"scripts": {
    "sublime2": "\"C:\\Sublime Text\\sublime_text.exe\"",
},
→エラー: ‘C:\Sublime’ is not recognized 半角スペースで切られて実行されたっぽい
ダブルクォートでエスケープできていない。 色々試したが、結局できなかったので
環境変数PATHにsublime_textとして登録した後、
"scripts": {
    "sublime2": "sublime_text .",
},
とする事で解決。
この時点で自分のPCでしか動作しないので注意。
駄目な形のオンリーワンである。

npm-scriptの並列起動

軽く調べてみた所、
initした時にできるサンプルのように
「echo ~~ && exit ~~」
&&で直列、&で並列を指定できるという記述を見たが、
windows機では動作しないとの事。
javascript – How can I run multiple npm scripts in parallel? – Stack Overflow
windowsの場合、どちらも直列で左辺が終了すると右辺が実行される。
(→エディタを終了させるとgulpが始まる) 同ページ内にパイプを使ってみてはどうか、という記述あり。
試してみる。
//package.json
"scripts": {
    "gulp": "npm run gulp",
    "sublime": "sublime_text .",
    "start": "sublime_text  | gulp",
  },
なんかしらんが希望通りの動作した。 パイプが無理やり左辺の終了を伝えてくれるのだろうか、と考えたが、
順番を入れ替えたら動作しなかったのでおそらく違う。
意味がわからん。

感想

理屈がわからないと怖いのでおとなしく並列用のパッケージを使おう。
パイプの謎はともかく、実行ファイルのパスにスペースが含まれる場合の解決策は知っておきたい。
引き続き調査する。

gulp-sassが2回更新しないと適用されない問題

概要

gulpを使う場合、処理Aで生成したファイルを
処理Bで使用したい場合は処理A→処理Bとseriesでつなぐのではなく、
処理(A+B)を用意する必要がある

問題の具体例

gulp-sassでコンパイルしたcssを見たら
要素ごとにメディアクエリが出力されていた。 大した量でもないのだけれど、
やはり気持ち悪いのでなんとかしたい。 調べてみると
pleeeaseのmqpacker機能でまとめてくれるらしい。
gulp-pleeease – npm

失敗例

以下のコードで試す。(失敗する)
// gulpfile.js

// sass
gulp.task('sass', done => {
  gulp.src('./css/style.scss')
  .pipe(sass({outputStyle: 'expanded'}))
  .pipe(gulp.dest('./css'))
  done()
});

// pleeease
gulp.task('pleeease', done => {
  gulp.src('./css/style.css')
  .pipe(pleeease({
    mqpacker: true
  }))
  .pipe(rename({
    suffix: '.min',
    extname: '.css'
  }))
  .pipe(gulp.dest('./css'))
  done()
});

// watch
gulp.task('watch', () => {
  gulp.watch('./css/*.scss', gulp.series('sass','pleeease'));
  //  ………
})
このまま実行するとstyle.cssが見つからないとエラーが出る。
seriesの時点で中身のtaskごとのsrcをチェックしているっぽい。 なので

解決策

// gulpfile.js

// sass and pleeease
gulp.task('sass_and_pleeease', done => {
  gulp.src('./css/style.scss')
  .pipe(sass({outputStyle: 'expanded'}))
  .pipe(pleeease({
    mqpacker: true
  }))
  .pipe(rename({
    suffix: '.min',
    extname: '.css'
  }))
  .pipe(gulp.dest('./css'))
  done()
});

// watch
gulp.task('watch', () => {
  gulp.watch('./css/*.scss', gulp.task('sass_and_pleeease'));
  //  ………
})
解決。
当たり前と言えば当たり前なのだけれども。 表題の件は
すでにstyle.cssがある環境で上記のコードを実行したため、
エラーが出ずにいらない苦労した、という話でした。 というか、そもそもpleeeaseでsassコンパイルできるっぽい。
追加でいらない苦労の可能性が。

node.jsで脆弱性のあるパッケージを手動で更新した

概要

gulp-sass使おうとしたら脆弱性があると言われた。
内部で呼ばれている古いtarが原因だった。
悪いの承知でgulp-sass内のtarを手動で最新版に代えた。
良い子は作者にリクエストして修正を待とうね。
npm auditで検出された脆弱性
npm auditで検出された脆弱性

やったこと

package.jsonを書き換える

※大元の方じゃないので注意。
node_modules
└ node-gyp
 └ package.json ←こいつを書き換える dependenciesの
“tar”: “^2.2.2”,

“tar”: “^4.4.8”,
に書き換える。

インストールと修理

書き換えたら
npm install
して再インストールした後に
npm audit fix
するとキレイにしてくれる。
念の為、
npm audit
して「found 0 vulnerabilities」と表示される事を確認しておく。

npm list [パッケージ名]でバージョン確認

さらに心配ならば
npm list tar
して「tar@2.2.2」が「tar@4.4.8」になっている事を確認しよう。
`-- gulp-sass@4.0.2
  `-- node-sass@4.12.0
    `-- node-gyp@3.8.0
      `-- tar@4.4.8

注意事項

パッケージgulp-sassの依存関係を勝手に書き換えているので動作保証外。
当然である。
本来は作者の方に連絡して直してもらうのがスジ。
…が、実際に動いているプロジェクトの中で発生したらそんな悠長な事言ってられないのも事実。
あくまで自己責任の緊急措置、ということでひとつ。

参考

node.js – npm audit Arbitrary File Overwrite – Stack Overflow

Boostnoteからwordpressに投稿する時に注意する事

概要

すばらしきnoteツール「Boostnote」に
wordpressに直接投稿できる機能があるので試した。
まだ、この機能の使い勝手はイマイチだったのでコピペ運用を選んだ。

Boostenoteとは

すっごい便利なメモ帳。
書いたテキストをフォルダとタグで管理できる。
スッキリとしたUIでとても使いやすい。
markdown記法の入門に最適。
導入も楽、設定も楽なのでとりあえずインストールしよう。
Boostnote | Boost Happiness, Productivity, and Creativity.

wordpressへの投稿機能の設定

わかりやすく解説してくれているサイトがあったのでご紹介。
BoostnoteからWordPressへの記事の上げ方 – galeの日記
要約すると、
applicationプラグインを入れてパスワードを発行して、
Boostnoteの設定画面に入力するだけ。 注意事項は以下2点
  • ユーザー名は「wordpress側のユーザー名」(ログイン時に使うもの)
  • applicationプラグインが発行するパスワードは 区切りのスペースを取り除いて入力する
再発行はいくらでもできるので気軽に試せる。

アップロード機能はまだ不便だった

各挙動を記載する。

一番最初のh1が記事タイトルとして使われる

タイトルタグなど特別な指定しなくても
ノート内の最初のh1がタイトルに入ってくれた。 …が、URLも同様で
「http://(ドメイン)/(記事タイトル) 」
になった。 仕方ないのだけれど都合が悪い。

クラシックブロックとして扱われる

ノート全体が1つのクラシックブロックとして投稿された。
クラシックブロックの中で
「h1」や「p」「blockquote」などのhtmlタグがついていた。

「コード(バッククォート3つで始まるヤツ)」はうまく動作しない

余計な数字がはみ出てついてきた。
見た感じ、行番号が余分に反映されているように見える。

Boostnote側でつけたタグは無くなる

Boostnote側でノートにつけたタグは無くなる。
wordpress側に同じ名前、同じslugのタグを作成しておいても反映されなかった。

アップロード先の使い分けはできない

ノートを作成し、
localhostにアップロードできたのを確認した後、
Boostnoteのアップロード先を本番環境に指定し、
「Update Blog」するとエラーが起きる(設定ミスと言われる)。

憶測だけどノートがアップロードされたURLを記憶しているのだと思う。
そこだけを修正する方法は見つけられなかった。
新規にノートを作成するしかない。

逆にアップロードされたwordpress側の記事を削除しても
Boostnote側のノートには「Update Blog」が表示された。
選択したら新規に作成してくれたので気にする必要はなかった。

画像はアップロードされない

imgタグは挿入されるが
srcがBoostnoteのstorageに指定されているので画像は表示されない。
こんな感じ。
<img src=': storage/1234-5678-9012/gazou.jpg' alt="gazou">
ローカルの画像保存フォルダを指定する「:storage」がそのまま入っていた。
当然web上では参照できない。

markdownをコピペ。これだ。

画像もタグもカテゴリもURLも設定できないのはツラい。 Boostnote側でも
アップロード済みのノートと
そうではないノートの見分けがつかないのも不満点。

でも Boostnoteの書き心地はとても良い ので使っていきたい。

思案の結果、答えが出た。
Boostnoteで下書きしてwordpressにコピペ。 これだ。

もちろんwordpress側にmarkdownプラグインが入っている必要がある。

開発者様から石投げられそうな運用だが仕方ない。
あくまでwordpressとの連携機能に不満があるだけで、
Boostnoteが素晴らしいツールであることに変わりはない。
インストールナウ!

electron-builderでwindows用インストーラーを作る時の設定

概要

electron-builderでwindowsのインストーラーを作成する時は
「NSIS」を指定すると便利。

package.jsonの書き方

build節に以下の指定
"build": {
    "win": {
      "target": "nsis"
    },
    "nsis":{
      "oneClick": false,
      "allowToChangeInstallationDirectory": true
    }
}
“win”の”target”を”nsis”を指定。
他OSやインストーラーを希望する場合は以下を参照
Common Configuration – electron-builder

NSISの設定

オプション詳細はここ
NSIS – electron-builder
全部英語なので感覚で勝負する。

インストール先

  • oneClick:ワンクリックインストーラー。
    trueにするとインストーラークリックした時点で何も聞かれずインストール&実行する。
  • allowToChangeInstallationDirectory:保存場所指定の許可
    trueにするとユーザーがインストール先を指定できる。
    ※これを使う場合は「oneClickをfalseにしろ」って怒られた
これでインストール先をたずねてくれるようになった

インストーラーのアイコン

NSISインストーラーのアイコンは
buildフォルダのinstallerIcon.icoを参照してくれる。
(※”installerIcon”でパス指定もできる)

Defaults tobuild/installerIcon.icoor application icon.
Defaults tobuild/uninstallerIcon.icoor application icon.

firefoxのレスポンシブモードでtargetが_blankのformはPOSTされない不具合

概要

題字の通り。
解決策はレスポンシブモードを止めれば良い。
ルー大柴みたい。

解決策

  • レスポンシブモードをやめる
  • target=_blankをやめる
上記条件の2つを併せた時に発現するので
どちらか止めれば良い。

javascriptを使う

どうしても新しいタブにPOSTしたいのであれば
javascript使ってどうにかするしかない。 ajaxでPOSTすると新しいタブに開けないので
通信成功時に無名window.open()してcontentだけ書き換える必要がある。 そこまでやって
今回のケースではformが要らない事に気づく。

雑感

前は出来た気がするんだがどうだったか。
やっぱりQuontum以降のレスポンシブモードは何かおかしい。