ExcelJSのテーマを変更する

  • このエントリーをはてなブックマークに追加

ExcelJSでXLSXファイルを出力すると、古いOfficeのテーマが適用されます。
それは同梱されているテーマファイルが古いOfficeのテーマだからです。

exceljs/lib/xlsx/xml/link
exceljs/lib/xlsx//xml/
theme1.js
theme1.xml

例えばフォントがMS Pゴシックだったりします。新しいテーマは游ゴシック

新しいテーマを利用する方法

まずテーマファイルを用意します。
Microsoft 365のEXCELでファイルを作成しXLSXファイルとして保存します。XLSXはZIPファイルなので拡張子をZIPにして中身を取り出します。中身は以下の構造になっており、xl/theme/theme1.xmlが該当するテーマファイルです。

./[Content_Types].xml
./_rels
./_rels/.rels
./docProps
./docProps/app.xml
./docProps/core.xml
./xl
./xl/_rels
./xl/_rels/workbook.xml.rels
./xl/styles.xml
./xl/theme
./xl/theme/theme1.xml
./xl/workbook.xml
./xl/worksheets
./xl/worksheets/sheet1.xml

ExcelJSではテーマファイルを扱う正規のInterfaceがありません。そのため少し回りくどい方法で設定する必要があります。ライブラリのバージョンが変わるとこの方法では適用できなるかもしれません。

my-theme1.js
module.exports =
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office テーマ"><a:themeElements><a:clrScheme name="Office"><a:dk1><a:sysClr val="windowText" lastClr="000000"/></a:dk1><a:lt1><a:sysClr val="window" lastClr="FFFFFF"/></a:lt1><a:dk2><a:srgbClr val="0E2841"/></a:dk2><a:lt2><a:srgbClr val="E8E8E8"/></a:lt2><a:accent1><a:srgbClr val="156082"/></a:accent1><a:accent2><a:srgbClr val="E97132"/></a:accent2><a:accent3><a:srgbClr val="196B24"/></a:accent3><a:accent4><a:srgbClr val="0F9ED5"/></a:accent4><a:accent5><a:srgbClr val="A02B93"/></a:accent5><a:accent6><a:srgbClr val="4EA72E"/></a:accent6><a:hlink><a:srgbClr val="467886"/></a:hlink><a:folHlink><a:srgbClr val="96607D"/></a:folHlink></a:clrScheme><a:fontScheme name="Office"><a:majorFont><a:latin typeface="Aptos Display" panose="02110004020202020204"/><a:ea typeface=""/><a:cs typeface=""/><a:font script="Jpan" typeface="游ゴシック Light"/><a:font script="Hang" typeface="맑은 고딕"/><a:font script="Hans" typeface="等线 Light"/><a:font script="Hant" typeface="新細明體"/><a:font script="Arab" typeface="Times New Roman"/><a:font script="Hebr" typeface="Times New Roman"/><a:font script="Thai" typeface="Tahoma"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="MoolBoran"/><a:font script="Knda" typeface="Tunga"/><a:font script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font script="Tibt" typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Times New Roman"/><a:font script="Uigh" typeface="Microsoft Uighur"/><a:font script="Geor" typeface="Sylfaen"/><a:font script="Armn" typeface="Arial"/><a:font script="Bugi" typeface="Leelawadee UI"/><a:font script="Bopo" typeface="Microsoft JhengHei"/><a:font script="Java" typeface="Javanese Text"/><a:font script="Lisu" typeface="Segoe UI"/><a:font script="Mymr" typeface="Myanmar Text"/><a:font script="Nkoo" typeface="Ebrima"/><a:font script="Olck" typeface="Nirmala UI"/><a:font script="Osma" typeface="Ebrima"/><a:font script="Phag" typeface="Phagspa"/><a:font script="Syrn" typeface="Estrangelo Edessa"/><a:font script="Syrj" typeface="Estrangelo Edessa"/><a:font script="Syre" typeface="Estrangelo Edessa"/><a:font script="Sora" typeface="Nirmala UI"/><a:font script="Tale" typeface="Microsoft Tai Le"/><a:font script="Talu" typeface="Microsoft New Tai Lue"/><a:font script="Tfng" typeface="Ebrima"/></a:majorFont><a:minorFont><a:latin typeface="Aptos Narrow" panose="02110004020202020204"/><a:ea typeface=""/><a:cs typeface=""/><a:font script="Jpan" typeface="游ゴシック"/><a:font script="Hang" typeface="맑은 고딕"/><a:font script="Hans" typeface="等线"/><a:font script="Hant" typeface="新細明體"/><a:font script="Arab" typeface="Arial"/><a:font script="Hebr" typeface="Arial"/><a:font script="Thai" typeface="Tahoma"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="DaunPenh"/><a:font script="Knda" typeface="Tunga"/><a:font script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font script="Tibt" typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Arial"/><a:font script="Uigh" typeface="Microsoft Uighur"/><a:font script="Geor" typeface="Sylfaen"/><a:font script="Armn" typeface="Arial"/><a:font script="Bugi" typeface="Leelawadee UI"/><a:font script="Bopo" typeface="Microsoft JhengHei"/><a:font script="Java" typeface="Javanese Text"/><a:font script="Lisu" typeface="Segoe UI"/><a:font script="Mymr" typeface="Myanmar Text"/><a:font script="Nkoo" typeface="Ebrima"/><a:font script="Olck" typeface="Nirmala UI"/><a:font script="Osma" typeface="Ebrima"/><a:font script="Phag" typeface="Phagspa"/><a:font script="Syrn" typeface="Estrangelo Edessa"/><a:font script="Syrj" typeface="Estrangelo Edessa"/><a:font script="Syre" typeface="Estrangelo Edessa"/><a:font script="Sora" typeface="Nirmala UI"/><a:font script="Tale" typeface="Microsoft Tai Le"/><a:font script="Talu" typeface="Microsoft New Tai Lue"/><a:font script="Tfng" typeface="Ebrima"/></a:minorFont></a:fontScheme><a:fmtScheme name="Office"><a:fillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:lumMod val="110000"/><a:satMod val="105000"/><a:tint val="67000"/></a:schemeClr></a:gs><a:gs pos="50000"><a:schemeClr val="phClr"><a:lumMod val="105000"/><a:satMod val="103000"/><a:tint val="73000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:lumMod val="105000"/><a:satMod val="109000"/><a:tint val="81000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="5400000" scaled="0"/></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:satMod val="103000"/><a:lumMod val="102000"/><a:tint val="94000"/></a:schemeClr></a:gs><a:gs pos="50000"><a:schemeClr val="phClr"><a:satMod val="110000"/><a:lumMod val="100000"/><a:shade val="100000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:lumMod val="99000"/><a:satMod val="120000"/><a:shade val="78000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="5400000" scaled="0"/></a:gradFill></a:fillStyleLst><a:lnStyleLst><a:ln w="12700" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/><a:miter lim="800000"/></a:ln><a:ln w="19050" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/><a:miter lim="800000"/></a:ln><a:ln w="25400" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/><a:miter lim="800000"/></a:ln></a:lnStyleLst><a:effectStyleLst><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="57150" dist="19050" dir="5400000" algn="ctr" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="63000"/></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:solidFill><a:schemeClr val="phClr"><a:tint val="95000"/><a:satMod val="170000"/></a:schemeClr></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="93000"/><a:satMod val="150000"/><a:shade val="98000"/><a:lumMod val="102000"/></a:schemeClr></a:gs><a:gs pos="50000"><a:schemeClr val="phClr"><a:tint val="98000"/><a:satMod val="130000"/><a:shade val="90000"/><a:lumMod val="103000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="63000"/><a:satMod val="120000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="5400000" scaled="0"/></a:gradFill></a:bgFillStyleLst></a:fmtScheme></a:themeElements><a:objectDefaults><a:lnDef><a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="2"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="1"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1"/></a:fontRef></a:style></a:lnDef></a:objectDefaults><a:extraClrSchemeLst/><a:extLst><a:ext uri="{05A4C25C-085E-4340-85A3-A5531E510DB2}"><thm15:themeFamily xmlns:thm15="http://schemas.microsoft.com/office/thememl/2012/main" name="Office Theme" id="{2E142A2C-CD16-42D6-873A-C26D2A0506FA}" vid="{1BDDFF52-6CD6-40A5-AB3C-68EB2F1E4D0A}"/></a:ext></a:extLst></a:theme>';
const workbook = new ExcelJS.Workbook();
workbook.model = Object.assign({}, workbook.model, { themes: { theme1: require('./my-theme1') } });

解説

JSDocでObjectの属性名補完

  • このエントリーをはてなブックマークに追加

TypeScriptで任意の文字列を受け取るが、ある程度の定数を補完したい場合、|'aaa'|'bbb'|(string&{})で定義できる。
これの objectの属性版では{ aaa?: number, bbb?: number, [key: string]: unknown }と定義する。

JSDocでは以下のように定義する。

Record<string, unknown> & { aaa?: number, bbb?: number }

{}で定義するとLinterに怒られる。なのでRecordを使う。

Don't use `{}` as a type. `{}` actually means "any non-nullish value".
- If you want a type meaning "any object", you probably want `object` instead.
- If you want a type meaning "any value", you probably want `unknown` instead.
- If you want a type meaning "empty object", you probably want `Record<string, never>` instead.
- If you really want a type meaning "any non-nullish value", you probably want `NonNullable<unknown>` instead.eslint@typescript-eslint/ban-types

なお警告では Record<string, never> を使えと書いてありますが、この記事では Record<never, never> を使えと書いてある。

参考

GitHub CLIの通信ログを見る

  • このエントリーをはてなブックマークに追加

忘れがちなので。GH_DEBUG=1だけだと通信のログが見れないので、通信のログを見たい場合はGH_DEBUG=apiを設定する。

GH_DEBUG=1
GH_DEBUG=api

参考

CoodespacesのTokenのパーミッション

  • このエントリーをはてなブックマークに追加

GitHub Codespacesのデフォルトの権限設定は弱い。

トークンのスコープは、codespace が作成されたリポジトリへのアクセス権によって異なります。

基本的にはそのRepositoryに対する権限のみがGRANTされている。
他のレポジトリや組織範囲に対しての権限が必要な場合はdevcontainer.jsonに記述してrebuildする必要がある。

なお、devcontainer.jsonに指定できるRepositoryは1種類のみである。
1種類のみなので以下の設定はできない。仮に指定しても1番目の指定のみが有効になる。
複数指定したい場合は、ワイルドカードを利用するしかない。

{
"customizations": {
"codespaces": {
"repositories": {
"example-org/repo1": {
"permissions": {
"actions": "write",
"checks": "read",
"contents": "read",
"deployments": "write",
"discussions": "read",
"issues": "write",
"packages": "read",
"pages": "read",
"pull_requests": "write",
"repository_projects": "read",
"statuses": "write",
"workflows": "write"
}
},
"example-org/repo2": {
"actions": "read",
"checks": "read",
"contents": "read",
"deployments": "write",
"discussions": "read",
"issues": "read",
"packages": "read",
"pages": "read",
"pull_requests": "read",
"repository_projects": "read",
"statuses": "read",
"workflows": "read"
}
}
}
}
}

ワイルドカードを利用する場合は、以下のようになる。(example-org/*)
また、種別毎に指定しない場合は "permissions": "read-all", "permissions": "write-all" の記述が可能。

{
"customizations": {
"codespaces": {
"repositories": {
"example-org/*": {
"permissions": {
"actions": "write",
"checks": "read",
"contents": "read",
"deployments": "write",
"discussions": "read",
"issues": "write",
"packages": "read",
"pages": "read",
"pull_requests": "write",
"repository_projects": "read",
"statuses": "write",
"workflows": "write"
}
}
}
}
}
}

なお、VSCode内でrebuildをしても権限は反映されなかったので、UIから作り直す必要があった。

参考

esbuildのwasmを使う

  • このエントリーをはてなブックマークに追加

Windowsではコード署名が付いていないEXEを実行できない環境があります。
esbuildのexeファイルはコード署名がありません。そしてコード署名には対応しないことがIssueでやりとりされています。(参考情報を参照)

package.jsonoverrides機能を使って以下の定義を追加します。

"overrides": {
"esbuild": "npm:esbuild-wasm@latest"
}

確認した環境

vuepressを使っているところで、1.8系から1.9系の変更でesbuildを使うようになり、特定の環境でこけるようになりました。
以下がこけた時のログです。

npm install --save vuepress
npm WARN cleanup Failed to remove some directories [
npm WARN cleanup [
npm WARN cleanup 'C:\\Users\\User1\\AppData\\Local\\Temp\\work1\\node_modules',
npm WARN cleanup [Error: EPERM: operation not permitted, rmdir 'C:\Users\User1\AppData\Local\Temp\work1\node_modules\browserify-sign\node_modules'] {
npm WARN cleanup errno: -4048,
npm WARN cleanup code: 'EPERM',
npm WARN cleanup syscall: 'rmdir',
npm WARN cleanup path: 'C:\\Users\\User1\\AppData\\Local\\Temp\\work1\\node_modules\\browserify-sign\\node_modules'
npm WARN cleanup }
npm WARN cleanup ],
npm WARN cleanup [
npm WARN cleanup 'C:\\Users\\User1\\AppData\\Local\\Temp\\work1\\node_modules\\@vuepress\\core',
npm WARN cleanup [Error: EPERM: operation not permitted, rmdir 'C:\Users\User1\AppData\Local\Temp\work1\node_modules\@vuepress\core'] {
npm WARN cleanup errno: -4048,
npm WARN cleanup code: 'EPERM',
npm WARN cleanup syscall: 'rmdir',
npm WARN cleanup path: 'C:\\Users\\User1\\AppData\\Local\\Temp\\work1\\node_modules\\@vuepress\\core'
npm WARN cleanup }
npm WARN cleanup ]
npm WARN cleanup ]
npm ERR! code 1
npm ERR! path C:\Users\User1\AppData\Local\Temp\work1\node_modules\esbuild
npm ERR! command failed
npm ERR! command C:\Windows\system32\cmd.exe /d /s /c node install.js
npm ERR! node:child_process:924
npm ERR! throw err;
npm ERR! ^
npm ERR!
npm ERR! <ref *1> Error: spawnSync C:\Users\User1\AppData\Local\Temp\work1\node_modules\esbuild-windows-64\esbuild.exe UNKNOWN
npm ERR! at Object.spawnSync (node:internal/child_process:1110:20)
npm ERR! at spawnSync (node:child_process:871:24)
npm ERR! at Object.execFileSync (node:child_process:914:15)
npm ERR! at Object.<anonymous> (C:\Users\User1\AppData\Local\Temp\work1\node_modules\esbuild\bin\esbuild:108:26)
npm ERR! at Module._compile (node:internal/modules/cjs/loader:1256:14)
npm ERR! at Module._extensions..js (node:internal/modules/cjs/loader:1310:10)
npm ERR! at Module.load (node:internal/modules/cjs/loader:1119:32)
npm ERR! at Module._load (node:internal/modules/cjs/loader:960:12)
npm ERR! at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
npm ERR! at node:internal/main/run_main_module:23:47 {
npm ERR! errno: -4094,
npm ERR! code: 'UNKNOWN',
npm ERR! syscall: 'spawnSync C:\\Users\\User1\\AppData\\Local\\Temp\\work1\\node_modules\\esbuild-windows-64\\esbuild.exe',
npm ERR! path: 'C:\\Users\\User1\\AppData\\Local\\Temp\\work1\\node_modules\\esbuild-windows-64\\esbuild.exe',
npm ERR! spawnargs: [ '--version' ],
npm ERR! error: [Circular *1],
npm ERR! status: null,
npm ERR! signal: null,
npm ERR! output: null,
npm ERR! pid: 0,
npm ERR! stdout: null,
npm ERR! stderr: null
npm ERR! }
npm ERR!
npm ERR! Node.js v18.17.1
npm ERR! node:internal/errors:865
npm ERR! const err = new Error(message);
npm ERR! ^
npm ERR!
npm ERR! Error: Command failed: node C:\Users\User1\AppData\Local\Temp\work1\node_modules\esbuild\bin\esbuild --version
npm ERR! node:child_process:924
npm ERR! throw err;
npm ERR! ^
npm ERR!
npm ERR! <ref *1> Error: spawnSync C:\Users\User1\AppData\Local\Temp\work1\node_modules\esbuild-windows-64\esbuild.exe UNKNOWN
npm ERR! at Object.spawnSync (node:internal/child_process:1110:20)
npm ERR! at spawnSync (node:child_process:871:24)
npm ERR! at Object.execFileSync (node:child_process:914:15)
npm ERR! at Object.<anonymous> (C:\Users\User1\AppData\Local\Temp\work1\node_modules\esbuild\bin\esbuild:108:26)
npm ERR! at Module._compile (node:internal/modules/cjs/loader:1256:14)
npm ERR! at Module._extensions..js (node:internal/modules/cjs/loader:1310:10)
npm ERR! at Module.load (node:internal/modules/cjs/loader:1119:32)
npm ERR! at Module._load (node:internal/modules/cjs/loader:960:12)
npm ERR! at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
npm ERR! at node:internal/main/run_main_module:23:47 {
npm ERR! errno: -4094,
npm ERR! code: 'UNKNOWN',
npm ERR! syscall: 'spawnSync C:\\Users\\User1\\AppData\\Local\\Temp\\work1\\node_modules\\esbuild-windows-64\\esbuild.exe',
npm ERR! path: 'C:\\Users\\User1\\AppData\\Local\\Temp\\work1\\node_modules\\esbuild-windows-64\\esbuild.exe',
npm ERR! spawnargs: [ '--version' ],
npm ERR! error: [Circular *1],
npm ERR! status: null,
npm ERR! signal: null,
npm ERR! output: null,
npm ERR! pid: 0,
npm ERR! stdout: null,
npm ERR! stderr: null
npm ERR! }
npm ERR!
npm ERR! Node.js v18.17.1
npm ERR!
npm ERR! at checkExecSyncError (node:child_process:885:11)
npm ERR! at Object.execFileSync (node:child_process:921:15)
npm ERR! at validateBinaryVersion (C:\Users\User1\AppData\Local\Temp\work1\node_modules\esbuild\install.js:94:32)
npm ERR! at C:\Users\User1\AppData\Local\Temp\work1\node_modules\esbuild\install.js:240:5 {
npm ERR! status: 1,
npm ERR! signal: null,
npm ERR! output: [
npm ERR! null,
npm ERR! Buffer(0) [Uint8Array] [],
npm ERR! Buffer(1309) [Uint8Array] [
npm ERR! ... 1209 more items
npm ERR! ]
npm ERR! ],
npm ERR! pid: 38656,
npm ERR! stdout: Buffer(0) [Uint8Array] [],
npm ERR! stderr: Buffer(1309) [Uint8Array] [
npm ERR! ... 1209 more items
npm ERR! ]
npm ERR! }
npm ERR!
npm ERR! Node.js v18.17.1

この環境でoverrides設定を入れればwasm版で動くようになりました。

参考

JSのoverloadはfunctionでないと認識しない

  • このエントリーをはてなブックマークに追加

関数定義をconstで行っていると認識しなかった。

/**
* @overload
* @param {true} flag
* @param {Ref<MyClass|undefined>}
*/
/**
* @overload
* @param {false} flag
* @param {Ref<MyClass>}
*/
const myFunction = (flag) => {
};

functionで定義するとoverloadを認識します。
また、コメントは分割しないとLinterに怒られました。

/**
* @overload
* @param {true} flag
* @param {Ref<MyClass|undefined>}
*/
/**
* @overload
* @param {false} flag
* @param {Ref<MyClass>}
*/
function myFunction(flag) {
}

HP OMEN45Lの電源交換

  • このエントリーをはてなブックマークに追加

去年ゲーミングPCを購入していたのですが、最近ゲームをやっていると電源が落ちる。
そして電源が落ちた後は放電をしないと暫く電源が付かない事象が頻繁に発生していました。

最初は温度かなと思っていたのですが、最近のグラボは瞬間的に電力が必要になることがあるらしく、電源が怪しいと思い電源を買い換えました。

HP OMEN 45Lの性能

  • CPU: Core i7 12700K
  • メモリ: DDR4-3733 16GB x2
  • グラボ: RTX 3080 Ti 12GB
  • SSD: WD_Black SN850 (2TB)
  • 電源800W GOLD(クーラーマスター製)

この機種と同じです。

ここにSSDを1つ追加とメモリを32GB*2を追加しています。
また、周辺機器としてSound Blaster GC7とDEPSTECHのWebカメラを接続しています。

購入した電源

同じくクーラーマスター製のATX3.0に対応した1250Wの電源です。同じメーカーでATX3.0に対応した電源がこれしかありませんでした。ATX3.0にした理由は瞬間的な消費電力にも耐えられる規格に沿っているからです。
MWE Gold V2 FM 1250W ATX3.0 MPE-C501-AFCAG-3JP

電源が接続できない

HP OMENのマザーボードが特殊で付属品だけでは取り付け不可能です。
この電源にはCPU用の補助電源ケーブルとして8ピンが1つ、4ピン+4ピンが1つ付いています。
OMENのマザーボード側は4ピンが2つです。

4PIN+4PINの形状は通常以下の形式です。(●は台形の形です)
黒い■●はオスピンで、自分側を向いている状態です。(刺す時は反転します)

爪  爪
●■ ●●
■● ●●

8PINの形状は以下の形式です。

●■■●
■●●■

この向きを無視して接続するとショートしてしまいます。

OMENのマザーボードは

   爪
   ◻︎⚪︎
   ⚪︎◻︎

⚪︎◻︎
◻︎⚪︎爪

向きを揃えると

爪  爪
◻︎⚪︎ ◻︎⚪︎
⚪︎◻︎ ⚪︎◻︎

さらに電源付属の4+4ケーブルは通常の4+4の形状ではなく、4+4のくせに8ピンの以下の形式でした。通常4+4の場合であれば片側が全部●なので入るのですが、この形式では片方は入るけど片方は入らないということに。

●■■●
■●●■

解決策

4ピンの延長ケーブルを買っても形状の変換ができないのでダメです。
8ピンを12ピンに増やすケーブルを使います。
これを購入しました。

これを使う事で、以下の4+4+4の形式になります。

●■■● ●■
■●●■ ■●

つまり、以下の形状が2つできます。

●■
■●

このオスピンであればマザーボード側のメスピンに刺すことができます。(刺すときは向きがくるりと反転するので以下のようになり刺すことができます)

■● ⇒ ◻︎⚪︎
●■ ⇒ ⚪︎◻︎

罠が多すぎる…
電源を交換してからは落ちなくなりました。

有機ELのゲーミングモニター(ASUS PG27AQDM)を購入

  • このエントリーをはてなブックマークに追加

買ったやつはこれです。
現時点で有機ELのゲーミングモニタはこれの他にLGのがもう1つ、2種類しか販売していません。
どちらも240Hz1対応の有機ELパネルです。

パソコン工房で買いました。
店舗に行ったときは売り切れだったのですが別店舗に在庫があるとのことで、10秒ほど悩みましたがその場で買いました。ゴールデンウィーク中に使いたかったむねを伝えると、どうにかこうにか早く到達するように手配をしてくれて、その日はもうお店が閉まるくらいの時間だったのに、結果として翌々日には届きました。感謝しかない!

ドライバのインストールもしましょう。

ついでにメモリとSSDも買いました。

reviewdog/stylelintが動かない

  • このエントリーをはてなブックマークに追加

reviewdog便利です。
stylelint用のactionがあるので、設定してみたのですがStylelintでひっかかるコードをPushしても報告してくれません。

該当コードは以下のようになっています。

entrypoint.sh
if [ "${INPUT_REPORTER}" == 'github-pr-review' ]; then
# Use jq and github-pr-review reporter to format result to include link to rule page.
$(npm bin)/stylelint "${INPUT_STYLELINT_INPUT:-'**/*.css'}" --config="${INPUT_STYLELINT_CONFIG}" --ignore-pattern="${INPUT_STYLELINT_IGNORE}" -f json \
| jq -r '.[] | {source: .source, warnings:.warnings[]} | "\(.source):\(.warnings.line):\(.warnings.column):\(.warnings.severity): \(.warnings.text) [\(.warnings.rule)](https://stylelint.io/user-guide/rules/\(.warnings.rule))"' \
| reviewdog -efm="%f:%l:%c:%t%*[^:]: %m" -name="${INPUT_NAME:-stylelint}" -reporter=github-pr-review -level="${INPUT_LEVEL}" -filter-mode="${INPUT_FILTER_MODE}" -fail-on-error="${INPUT_FAIL_ON_ERROR}"
else
$(npm bin)/stylelint "${INPUT_STYLELINT_INPUT:-'**/*.css'}" --config="${INPUT_STYLELINT_CONFIG}" --ignore-pattern="${INPUT_STYLELINT_IGNORE}" \
| reviewdog -f="stylelint" -name="${INPUT_NAME:-stylelint}" -reporter="${INPUT_REPORTER:-github-pr-check}" -level="${INPUT_LEVEL}" -filter-mode="${INPUT_FILTER_MODE}" -fail-on-error="${INPUT_FAIL_ON_ERROR}"
fi

reporterにgithub-pr-reviewを設定した場合は動きますが、このモードはBotがレビュワーに入ってくるやつなのでgithub-or-checkを使いたい。そうすると、elseの方が実行されるわけですが、stylelintの結果をreviewdog -f=stylelint につなげても何も出力されません。
debugのためにteeオプションを付けると元の出力は表示されるので、Stylelint自体は動作しています。もしreviewdogも正しく処理されれば二重で表示されます。

npx stylelint "**/*.css" | reviewdog -f=stylelint -reporter=local -level=error -filter-mode=nofilter --tee

結論から言えば、--no-colorを指定する必要がありました。が、今のバージョンでは--no-colorを指定することができません。

npx stylelint "**/*.css" --no-color | reviewdog -f=stylelint -reporter=local -level=error -filter-mode=nofilter --tee

なので、このActionを使わずに、自分でLintを実行し、reviewdogにつなげる必要があります。

steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-node@v2
with:
node-version: '16'
cache: npm
cache-dependency-path: |
package-lock.json
- run: npm ci
- uses: reviewdog/action-setup@v1
- run: reviewdog -version
- name: stylelint
env:
# reviewdogはこの環境変数でTokenを参照する
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npx stylelint "**/*.css" --no-color \
| reviewdog -f="stylelint" -name="stylelint" -reporter="github-pr-check" -level="error" -filter-mode="nofilter" -fail-on-error="false"

これでreviewdogがannotationを付けたりと正しく報告してくれるようになりました。
※reviewdogのオプションは必要に応じて変更してください。

参考情報

Vue3でaxiosをMock化する

  • このエントリーをはてなブックマークに追加

APIのアクセスはaxiosでコールするけど、開発中はMockに差し替えるということをします。

mockにはaxios-mock-adapterを利用します。

mock.js
import MockAdapter from 'axios-mock-adapter'
const data = { world: "world" }
export default {
run(client) {
const mock = new MockAdapter(client, {delayResponse: 300})
mock.onGet("/api/hello").reply(200, data)
}
}

delayResponseを設定することで意図的に遅くすることができます。

mockの色々な書き方

直接JSONを返す

mock.onGet("/api/hello").reply(200, { hello: "world" })

関数の実行

mock.onGet("/api/hello").reply((config) => {
return [200, { hello: "world" }];
});

Queryの処理

ややこしいのは、config.paramsではないと言うことです。
/api/hello?name=taroとリクエストする場合は、正規表現で/\/api\/hello\?.*/と指定する必要があります。ここは良い感じに処理して欲しいですね…。なので、

function parseQueryString(url) {
const queryString = url.replace(/.*\?/, '')

const result = {}
if (queryString === url || !queryString) {
return result
}

const urlParams = new URLSearchParams(queryString)
urlParams.forEach((val, key) => {
if (Object.prototype.hasOwnProperty.call(result, key)) {
result[key] = [result[key], val]
} else {
result[key] = val
}
});

return result
}

mock.onGet(/\/api\/hello2?.*/).reply((config) => {
const params = parseQueryString(config.url)
return [200, { config, params }]
})

postされた内容を見る。FormDataの場合。

const formData = new FormData();
formData.append("name", "taro");
formData.append("flag1", "true");
const resp = await $client.post("/api/formPost", formData, {});
mock.onPost("/api/post").reply(config => {
const formData = config.data
const name = formData.get("name")
...
})

PostされたJSONを見る

const resp = await $client.post("/api/postJson", {
name: "hello",
message: "world",
});

config.dataは文字列なのでJSON.parseする。

mock.onPost("/api/postJson").reply((config) => {
const data = JSON.parse(config.data);
return [200, { data }];
});

わざとDelayさせる

delayResponseの全体設定とは別に、個別にDelayさせる。
Promiseを返して、setTimeoutが終わった時にresolveする。

mock.onGet("/api/delayHello").reply((config) => {
const delay = 5000;
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([200, { hello: "world" }]);
}, delay);
});
});

関連記事

参考情報