Wikipediaの日本語URLを短縮URLにするChrome拡張を作った

# 概要
Wikipediaの日本語ページのURLをコピペした際にURLが

```
https://ja.wikipedia.org/wiki/ワニ
https://ja.wikipedia.org/wiki/%E3%83%AF%E3%83%8B
```

のようにパーセントエンコーディングされてしまうので、
Wikipedia自体が持っているページIDのURLに変換するChrome拡張を作った

```
https://ja.wikipedia.org/wiki/ワニ
https://ja.wikipedia.org/?curid=64684
```

https://chrome.google.com/webstore/detail/wiki-url-shortener/nankjdiolkjcapfeniemgppodcfigcfg

# 解説
## 仕組み
Wikipediaにはページごとに固有のIDを持っており、そのIDを`?curid=ID`の形で指定してあげることでリンクが作れる。
ページのScriptタグにcuridが埋め込まれているので、それを取得してURLをクリップボードに貼り付けるようにした。

```html
<script>document.documentElement.className="client-js";RLCONF={"wgCanonicalNamespace":"","wgCanonicalSpecialPageName":!1,"wgNamespaceNumber":0,"wgPageName":"ワニ","wgTitle":"ワニ","wgCurRevisionId":74694645,"wgRevisionId":74694645,"wgArticleId":64684,"wgIsArticle":!0,"wgIsRedirect":!1,"wgAction":"view","wgUserName":null,"wgUserGroups":["*"],"wgCategories":["PMIDマジックリンクを使用しているページ","参照方法","出典を必要とする節のある記事/2015年11月-12月","動物関連のスタブ項目","GND識別子が指定されている記事","LCCN識別子が指定されている記事","ワニ目","特定動物","生きている化石"],"wgBreakFrames":!1,"wgPageContentLanguage":"ja","wgPageContentModel":"wikitext","wgSeparatorTransformTable":["",""],"wgDigitTransformTable":["",""],"wgDefaultDateFormat":"ja","wgMonthNames":["","1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"wgMonthNamesShort":["","1月","2月",
"3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"wgRelevantPageName":"ワニ","wgRelevantArticleId":64684,"wgRequestId":"XcC0oApAAD4AAHy9tasAAADR","wgCSPNonce":!1,"wgIsProbablyEditable":!0,"wgRelevantPageIsProbablyEditable":!0,"wgRestrictionEdit":[],"wgRestrictionMove":[],"wgMediaViewerOnClick":!0,"wgMediaViewerEnabledByDefault":!0,"wgPopupsReferencePreviews":!1,"wgPopupsConflictsWithNavPopupGadget":!1,"wgVisualEditor":{"pageLanguageCode":"ja","pageLanguageDir":"ltr","pageVariantFallbacks":"ja"},"wgMFDisplayWikibaseDescriptions":{"search":!0,"nearby":!0,"watchlist":!0,"tagline":!0},"wgWMESchemaEditAttemptStepOversample":!1,"wgULSCurrentAutonym":"日本語","wgNoticeProject":"wikipedia","wgWikibaseItemId":"Q25363","wgCentralAuthMobileDomain":!1,"wgEditSubmitButtonLabelPublish":!0};RLSTATE={"ext.globalCssJs.user.styles":"ready","site.styles":"ready","noscript":"ready","user.styles":"ready","ext.globalCssJs.user":"ready","user":
"ready","user.options":"loading","user.tokens":"loading","ext.cite.styles":"ready","mediawiki.legacy.shared":"ready","mediawiki.legacy.commonPrint":"ready","mediawiki.toc.styles":"ready","wikibase.client.init":"ready","ext.visualEditor.desktopArticleTarget.noscript":"ready","ext.uls.interlanguage":"ready","ext.wikimediaBadges":"ready","ext.3d.styles":"ready","mediawiki.skinning.interface":"ready","skins.vector.styles":"ready"};RLPAGEMODULES=["ext.cite.ux-enhancements","site","mediawiki.page.startup","mediawiki.page.ready","mediawiki.toc","mediawiki.searchSuggest","ext.gadget.ReferenceTooltips","ext.gadget.suppressEnterAtSummaryBox","ext.gadget.checkSignature","ext.gadget.WikiMiniAtlas","ext.gadget.switcher","ext.centralauth.centralautologin","mmv.head","mmv.bootstrap.autostart","ext.popups","ext.visualEditor.desktopArticleTarget.init","ext.visualEditor.targetLoader","ext.eventLogging","ext.wikimediaEvents","ext.navigationTiming","ext.uls.compactlinks","ext.uls.interface",
"ext.cx.eventlogging.campaigns","ext.centralNotice.geoIP","ext.centralNotice.startUp","skins.vector.js"];</script>
```
`"wgArticleId":64684`←これ


## コード解説
ソースコードは以下
https://github.com/sugawani/wiki-ja-url-shortener

### manifest.json
```json
{
    "author": "sugawani",
    "homepage_url": "https://twitter.com/nek0roll",
    "manifest_version": 2,
    "name": "wiki-url-shortener",
    "description": "wikipedia日本語URLを省略するやつ",
    "version": "1.0",
    "icons": {
        "16": "icons/16.png",
        "48": "icons/48.png",
        "128": "icons/128.png"
    },
    "content_scripts": [{
        "matches": ["https://*.wikipedia.org/*"],
        "js": ["content_scripts.js"]
    }],
    "background": {
        "scripts": ["background.js"],
        "persistent": false
    },
    "browser_action": {},
    "permissions": ["tabs"]
}
```
- `background.persistent`
    - Backgroundで実行し続ける必要はないので、拡張機能アイコンをクリックしたタイミングで動くように指定
    - https://developer.chrome.com/extensions/background_pages
- `browser_action`
    - 拡張機能アイコンクリックをトリガーで走らせたかったので指定
- `permissions`
    - `chrome.tabs.*`のAPIを使いたかったので`tabs`を指定
    - `background.js`から直接curidを取得しようと思ったけど、`background.js`からDOMを触れなかった

### background.js
```javascript
chrome.browserAction.onClicked.addListener(function(tab) {
    chrome.tabs.sendMessage(tab.id, "windowAction");
});
```
- `chrome.browserAction.onClicked.addListener`
    - 拡張機能アイコンのクリックを監視
- `crome.tabs.sendMessage`
    - `background.js`から`content_scripts.js`を呼び出すために定義

### content_scripts.js
```javascript
chrome.extension.onMessage.addListener(request => {
    if (request == "windowAction") {
        const scripts = document.querySelectorAll('script');
        const articleId = [...scripts].find(v => v.innerHTML.match(/wgArticleId.*?(\d+)/)).innerHTML.match(/wgArticleId.*?(\d+)/)[1];
        const url = `${location.protocol}//${location.hostname}/?curid=${articleId}`;
        navigator.clipboard.writeText(url);
    }
});
```
- `chrome.extension.onMessage.addListener`
    - `chrome.tabs.sendMessage`で送られてくるMessageを監視
- `[...scripts].find(v => v.innerHTML.match(/wgArticleId.*?(\d+)/)).innerHTML.match(/wgArticleId.*?(\d+)/)[1];`
    - `<script>`のnodeの中から`wgArticleId`が含まれるものを探して取得している
- `navigator.clipboard.writeText()`
    - `ClipboardAPI`でクリップボードに`curid?=ID`の形のURLを貼り付け
    - https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText

## 感想
Chrome拡張に関する情報は結構多くて、簡単に作れて楽しかった。
`background.js`->`content_scripts.js`の部分が無駄なので直接DOM触れるようにしてほしい:innocent: