第2世代のCloud Functionsで公開APIを作る
基本的にはただfunctionを作れば良いが、いったん非公開(未認証の呼び出しを許可しない)設定で作ってしまうと、Functionsの編集画面からは直せない。
作成画面:

これを後から「未認証の呼び出しを許可」に変えるには、functionの詳細画面右上の「Powered by Cloud Run」のリンクからCloud Runのページへ行き、セキュリティタブで設定変更する必要がある。

第2世代のCloud FunctionsはCloud Run上で動いているので、Cloud Runの一覧ページにもfunctionが存在するし、相互にリンクが置いてある。そちらからもログの確認や設定変更ができるし、どちらかにしかない設定項目もある。
Cloud Runのページでは編集はコンテナ単位になってしまうので、コードだけ編集したい場合はCloud Functionsのページから行う。
Astroでトップページを最新記事にしたい
トップページは常に最新記事にしたい、つまりビルドするごとに内容が変わる(かも)という状態にしたい。 WordPressなんかでトップページを「最新の投稿」にする、みたいな設定がある思うんですが、ああいうイメージです。
Routing -> Rest parameters -> undefined でできる
結論からすると、[...slug].astroで、pathにundefinedを指定するとトップレベルのindex.htmlになりました。痒いところに手が届いてて助かる……。
ドキュメント:Routing 🚀 Astro Documentation
index.astroに書けば…?
pages/index.astro に最新記事を取得して出力するコードを書いてももちろんできるんですが、個別記事を出力するファイル(つまりpages/posts/[slug].astroみたいなやつ)とほぼ同じことを書くことになるので、1つのファイルで済ませたいな、というのが前提でした。
もうちょっと具体的に
pages/[...slug].astroを用意するgetStaticPaths()関数に、記事を取得してきて配列を返すコードを書く- 配列の最後に、最新記事をコピーして
params.pathをundefinedに変更した要素を入れておく
こんな感じ
const paths = posts.map(post => { //...なんか記事データの処理 return { params: {path: `posts/${post.id}`}, props: { // } } }) const lastItem = Object.assign({params: {}, props: {}}, paths[paths.length - 1]) lastItem.params = {path: undefined} paths.push(lastItem) return paths
こうすると、pathがundefinedな要素は親階層のパスになるので、/dist/index.htmlに書き出される。
JavaScriptでクリップボードにコピー(2022年版)
※ 2017年に書いた記事が、2022年現在では非推奨になっているAPIを使っているので、改めて。
変わったところ
document.execCommand('copy')が仕様からなくなり、非推奨になりました(MDN)。今のところどのブラウザでも動作しますが、今後も動く保証はありません(とはいえ後方互換のために当面は動くと思いますが)。代わりにClipboard APIという仕様が整備されているので、新たに実装する場合はこちらを使うべきです。
HTMLとJavaScriptのコード
<p class="copyTarget">コピーしてもらいたいテキスト</p> <button class="copyBtn">クリップボードにコピーする</button>
function copyText () { const $target = document.querySelector('.copyTarget'); if (!$target) { return false; } const range = document.createRange(); range.selectNode($target); window.getSelection().removeAllRanges(); window.getSelection().addRange(range); // document.execCommand('copy'); // ←非推奨に。 navigator.clipboard.writeText($target.innerText); return false; } document.querySelector('.copyBtn').addEventListener('click', copyText, false);
テキストエリア内のコンテンツをコピーする場合
<textarea class="textarea">テキストエリアのテキスト</textarea> <button class="copyBtn">クリップボードにコピーする</button>
function copyText () { const $target = document.querySelector('.textarea'); if (!$target) { return false; } $target.select(); navigator.clipboard.writeText($target.value); return false; } document.querySelector('.copyBtn').addEventListener('click', copyText, false);
クリップボードからコピーする
<textarea class="textarea">テキストエリアのテキスト</textarea> <button class="copyBtn">クリップボードからコピーする</button>
function copyText () { const $target = document.querySelector('.textarea'); if (!$target) { return false; } navigator.clipboard.readText().then(clipText => { $target.value = clipText; }); return false; } document.querySelector('.copyBtn').addEventListener('click', copyText, false);
ユーザーの許可を求める表示が出ますが、許可するとクリップボードにあるテキストがテキストエリアの内容に置き換わります。
ElectronでPuppeteerを使う場合の複数プラットフォーム対応
Electronで作っているデスクトップアプリ内で、Puppeteerを使った時のメモです。
結果的には、各プラットフォーム用のChromiumを手動でダウンロードして追加し、Puppeteerに対してChromiumのパスを明示的に指定する必要がありました。
npm install puppeteerして開発しているうちは問題なかったのですが、開発環境と異なるプラットフォーム用にElectronをビルドして、単体のアプリケーションとして実行するとうまくいきませんでした。
Chromium revision is not downloaded. Run "npm install" or "yarn install" at Launcher.launch
というようなエラーが出ます。Chromiumが入ってないよ、とのこと。npm installしろ、と言われても、ビルドしてしまっているのでできません。
ビルドするプラットフォーム向けのChromiumを手動で追加する
Electronをビルドし、macOS版のアプリケーションのパッケージ内容を確認すると、/Contents/Resources/app.asar.unpacked/node_modules/puppeteer以下に、.local-chromiumというディレクトリがあり、さらにその中にmac-722234というディレクトリがありました。(6ケタの数字はバージョンのようなので、環境により異なると思います。)この中にChromium本体が入っています。
私の場合はMacで開発していて、Windows用にもビルドしましたが、win-unpacked/resources/app.asar.unpacked/node_modules/puppeteer/.local-chromiumの中にはmac-722234ディレクトリしかありません。そこで、ここにwin64-722234というディレクトリを作成し、Windows用のChromiumをダウンロードしてきて入れました。ディレクトリ構造としては、win64-722234/chrome-winの中にchrome.exeなどのファイルが入っている状態です。
Chromiumのダウンロードはこちらからできます:https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html
続いて、Puppeteerの起動時にこのChromiumを見つけられるようパスを指定します。GitHubにそのままのissueがありましたので参考にしました:Run from Electron · Issue #2134 · puppeteer/puppeteer · GitHub
これでMacでもWindowsでも問題なく、単体のアプリケーション上でPuppeteerが実行できるようになりました。
また、エラーの原因を調べるにあたっては、electron-logというnpmパッケージが便利でした。こちらが詳しいです:
[Electron] ログをファイルに記録する - electron-log
最後に蛇足ながら、
Web上のExcelファイルからデータを読み取る(Node.js)
備忘録。
const request = require('request'); const Excel = require('exceljs'); const getBuffer = (url) => { return new Promise((resolve, reject) => { request(url, {encoding: null}, (error, response, body) => { if (error !== null) { reject(null); } const buffer = new Buffer.from(body); resolve(buffer); }); }); } const buffer = await getBuffer('https://...'); if (buffer === null) { console.log('Couldn\'t get the file'); return; } const excel = new Excel.Workbook(); await excel.xlsx.load(buffer); const sheet = excel.worksheets[0]; const row = sheet.getRow(1); const cellValue = row.getCell('C').value; //...
exceljsというnpmを使った。ライセンスはMIT。
HTTP(S)リクエストのところで、{encoding: null}を入れておかないとExcelファイルとして読み込めずにエラーになる。
excel.xlsx.load()のところでawaitしてるので、asyncな関数内で使ってください。