Skip to content

Instantly share code, notes, and snippets.

@furyutei
Last active August 17, 2020 22:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save furyutei/bafadf032fd17fc67fb7bae5105a74e5 to your computer and use it in GitHub Desktop.
Save furyutei/bafadf032fd17fc67fb7bae5105a74e5 to your computer and use it in GitHub Desktop.
[JavaScript]はてなブログの古い記事に警告を出す試み

[JavaScript]はてなブログの更新日が古い記事に警告を出す試み

はてなブログ上で記事にしてありますので、そちらをご参照ください


はてなブログで、例えば1年以上前に更新(作成日にあらず)された記事に対して、

「この記事は n 年以上更新されていません。」 001

のような警告をだすサンプルです。

作成日基準で警告をだすのなら記事は見つかるのですが、作者が記事中やコメントでも述べられているとおり、これまではサイトマップ上のURLが

/sitemap.xml?page=<ページ番号>

のような構造(更新日付が新しい記事から順にページ上に並んでいて、それが複数ページある)だったため、ピンポイントに当該記事の情報を探すのが困難でした。

2020/04/01より、はてなブログのサイトマップの構造が変わり

/sitemap_periodical.xml?year=<作成年>&month=<作成月>

のように、作成月別の記事の更新情報にアクセスしやすくなったことにより、JavaScriptのみで実現しやすくなりました。

ソースコード

  1. ブログのフッタなどに貼り付け用スクリプトサンプル(hatena_diary_article_attention.js)
  2. 警告表示調整用サンプルCSS(hatena_diary_article_attention.css)

注意

  • ブログのフッタなどに貼り付ける場合、<script>~</script>で囲むのを忘れないこと
  • 残念ながら、Gist 上のコードは外部スクリプトとしては読み込めません(Content-Type: text/plain; charset=utf-8 のため)
  • async/await とか使っているので、モダンブラウザじゃないと動きません(笑)

元ネタ

  1. はてなブログで古い記事にメッセージを表示するスクリプト - Sprint Life
  2. 【2020年4月~】はてなブログのサイトマップが変わったようです - ((7回目の出直し🌻))
  3. 関連ツイート
div.article-attention {
display: block;
padding: 4px 8px;
margin: 8px 24px;
background: #ffffe0;
border: solid 2px #ff4500;
border-radius: 6px;
color: #f00;
font-weight: bolder;
}
time.last-modified {
font-size: 90%;
padding: 0;
margin: -14px 0 0;
}
// ■ はてなブログの記事に更新日時表示&古い記事に警告を出す
( async () => {
'use strict';
const
THRESHOLD_YEAR = 1, // THRESHOLD_YEAR 年以上前の記事に警告を出す
get_path = ( url ) => new URL( url || location.href ).pathname;
if ( document.querySelector( 'html' ).dataset.page != 'entry' ) return;
let header_elem = document.querySelector( '#main-inner article.entry header.entry-header' );
if ( ! header_elem ) return;
let time_info = ( () => {
/*
//let time_elem = document.querySelector( 'time[datetime][pubdate].updated' );
//if ( ! time_elem ) return null;
//let date = new Date( time_elem.getAttribute( 'datetime' ) );
//return {
// year : date.getFullYear(),
// month : 1 + date.getMonth(),
// day : date.getDate(),
//};
*/
let time_elem = header_elem.querySelector( 'div.date a time[pubdate]' );
if ( ! time_elem ) return null;
return {
year : parseInt( time_elem.querySelector( '.date-year' ).textContent.trim(), 10 ),
month : parseInt( time_elem.querySelector( '.date-month' ).textContent.trim(), 10 ),
day : parseInt( time_elem.querySelector( '.date-day' ).textContent.trim(), 10 ),
};
} )();
if ( ! time_info ) return;
let sitemap_xml_url = new URL( '/sitemap_periodical.xml?year=' + time_info.year + '&month=' + time_info.month, location.href ).href,
sitemap = await fetch( sitemap_xml_url )
.then( response => response.text() )
.then( ( xml_text ) => {
return new DOMParser().parseFromString( xml_text, 'text/xml' );
} )
.catch( ( error ) => {
console.error( 'fetch() or analyze error:', sitemap_xml_url, error );
} );
if ( ! sitemap ) return;
let current_path = get_path(),
matched_url_element = Array.from( sitemap.querySelectorAll( 'urlset > url' ) )
.filter( url_info => get_path( url_info.querySelector( 'loc' ).textContent ) == current_path )[ 0 ];
if ( ! matched_url_element ) return;
let last_modified_string = matched_url_element.querySelector( 'lastmod' ).textContent,
last_modified_date = new Date( last_modified_string ),
last_modified_elem = document.createElement( 'time' ),
threshold_date = ( threshold_date => threshold_date.setYear( threshold_date.getFullYear() - THRESHOLD_YEAR ) && threshold_date )( new Date () );
last_modified_elem.classList.add( 'last-modified' );
last_modified_elem.setAttribute( 'datetime', last_modified_date.toISOString() );
last_modified_elem.insertAdjacentHTML( 'beforeend', '最終更新日:' + last_modified_string.replace( /T.*$/, '' ) );
header_elem.querySelector( 'h1' ).after( last_modified_elem );
if ( threshold_date < last_modified_date ) return;
let not_modified_years = Math.floor( ( Date.now() - last_modified_date.getTime() ) / Math.round( 365.2422 * 24 * 60 * 60 * 1000 ) ),
warning_elem = document.createElement( 'div' );
warning_elem.classList.add( 'article-attention' );
warning_elem.insertAdjacentHTML( 'beforeend', 'この記事は ' + not_modified_years + ' 年以上更新されていません。<br />情報が古くなっているかもしれませんので、ご注意ください。' );
header_elem.after( warning_elem );
} )();
@furyutei
Copy link
Author

古い記事はこんな感じの警告が表示されます。

「この記事は n 年以上更新されていません。」 001

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment