Skip to content

Instantly share code, notes, and snippets.

@Phroneris
Last active December 21, 2020 22:03
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 Phroneris/18e55be4a38a5cc4db855e710f730da3 to your computer and use it in GitHub Desktop.
Save Phroneris/18e55be4a38a5cc4db855e710f730da3 to your computer and use it in GitHub Desktop.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- Minimal Theme designed by Artur Kim (http://arturkim.com) for Tumblr | version 1.5 -->
<!--
改造 by 森の子リスのミーコの大冒険(http://phroneris.com)
https://gist.github.com/Phroneris/18e55be4a38a5cc4db855e710f730da3
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{block:English}en{/block:English}{block:French}fr{/block:French}{block:German}de{/block:German}{block:Japanese}ja{/block:Japanese}{block:Italian}it{/block:Italian}{block:Spanish}es{/block:Spanish}{block:Polish}pl{/block:Polish}" lang="{block:English}en{/block:English}{block:French}fr{/block:French}{block:German}de{/block:German}{block:Japanese}ja{/block:Japanese}{block:Italian}it{/block:Italian}{block:Spanish}es{/block:Spanish}{block:Polish}pl{/block:Polish}">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>{block:IndexPage}{Title}{/block:IndexPage}{block:SearchPage}Search results for: {SearchQuery}{/block:SearchPage}{block:PostSummary}{PostSummary} | {Title}{/block:PostSummary}</title>
{block:Description}<meta name="description" content="{MetaDescription}" />{/block:Description}
<link rel="shortcut icon" href="{Favicon}" />
<link rel="apple-touch-icon" href="{PortraitURL-128}"/>
<link rel="alternate" type="application/rss+xml" href="{RSS}" />
<!-- DEFAULT VARIABLES -->
<meta name="if:April Fool BG" content="0"/>
<meta name="color:content border" content="#eee"/>
<meta name="color:link hover" content="#dd3333"/>
<meta name="color:Post" content="#555555"/>
<style type="text/css" media="screen">
/* Minimal Theme designed by Artur Kim (http://arturkim.com) for Tumblr | version 1.5 */
/* 改造 by 森の子リスのミーコの大冒険(http://phroneris.com) */
/* RESET */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0; padding: 0; border: 0; outline: 0; font-size: 100%; vertical-align: baseline; background: transparent;
}
body { line-height: 1; }
ol, ul { list-style: none; }
blockquote, q { quotes: none; }
blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; }
:focus { outline: 0; }
del { text-decoration: line-through; }
table { border-collapse: collapse; border-spacing: 0; }
/* GLOBAL ELEMENTS */
body { background: {block:IfAprilFoolBG}#def{/block:IfAprilFoolBG}{block:IfNotAprilFoolBG}#efd{/block:IfNotAprilFoolBG}; }
body, input, textarea { color: #000; font: 14px/20px "helvetica neue",helvetica,arial,sans-serif; }
p, ul, ol, dd, pre { margin-bottom: 20px; }
pre, code { font: 12px Monaco,monospace; line-height: 20px; }
blockquote { border-left: 5px solid #ddd; color: #555; font-style: italic; margin-bottom: 20px; padding-left: 10px; }
table { border: 1px solid #ccc; border-width: 1px 1px 0 1px; font-size: 14px; line-height: 20px; margin: 0 0 22px 0; text-align: left; }
caption { text-align: left; }
tr { border-bottom: 1px solid #ccc; }
th, td { padding: .7em 1.25em; }
hr { background-color: #ccc; border: 0; color: #555; height: 1px; margin-bottom: 20px; }
a:link, a:visited { color: #555; }
a:focus, a:hover, a:active { color: {color:link hover}; }
h1, h2, h3, h4, h5, h6 { font-weight:normal; clear:both; }
img { background: {color:content border}; }
a img:focus, a img:hover, a img:active { background: {color:link hover}; }
/* DEFAULT CSS */
#header .menu {
border-bottom: 1px solid #ccc;
margin: 0 auto 3px;
overflow: hidden;
padding: 20px 0 10px;
width: 900px;
}
#header #pages {
float: left;
width: 580px;
}
#header #pages ul {
float: left;
margin-bottom: 0;
}
#header #pages li {
float: left;
margin-right: 10px;
padding: 4px 10px 3px 0;
}
#header #pages a, #header #pages a:visited {
color: #555;
font-size: 16px;
text-decoration: none;
}
#header #pages a:focus, #header #pages a:hover, #header #pages a:active {
color: {color:link hover};
}
#header #search {
float: right;
}
#header #search input {
border: 1px solid #ccc;
line-height: 20px;
padding: 4px;
}
#header #search input.search-button {
background: #eee;
color: #555;
padding: 3px;
width: 60px;
}
#header #branding {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
margin: 0 auto 3px;
{block:IfNotHeaderImage}padding: 40px 0;{/block:IfNotHeaderImage}
width: 900px;
}
#header h1 a {
color: #111;
font: 80px Georgia,serif;
font-weight: normal;
line-height: 100px;
text-decoration: none;
}
#header h1 a:focus, #header h1 a:hover, #header h1 a:active {
color: {color:link hover};
}
#header img {
max-width: 900px;
}
#main {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
clear: both;
margin: 0 auto 3px;
overflow: hidden;
width: 900px;
}
#container {
border-right: 1px solid #ccc;
float: left;
min-height: 400px;
width: 580px;
}
.post-meta {
border-bottom: 1px solid #ccc;
color: #555;
overflow: hidden;
padding: 9px 0 0; /* 最後の0追加 */
}
.post-meta .type-date { /* 新設 */
border-bottom: 0;
border-bottom-color: {color:Post};
}
.post-meta .type-date:focus, .post-meta .type-date:hover, .post-meta .type-date:active { /* 新設 */
border-bottom: 0;
border-bottom-color: {color:link hover};
position: relative;
left: 5px;
}
.post-meta .type {
float: left; /* 以下追加 */
border-bottom: 1px solid;
border-bottom-color: inherit;
font-weight: bold;
padding: 0 10px 10px;
text-decoration: none;
}
.post-meta .date, .post-meta .comments, .post-meta .note-count {
float: left;
padding: 0 10px;
}
.post-meta .date { /* 追加 */
text-decoration: underline;
}
.post-content {
padding: 30px 30px 60px;
}
.post-content div:last-child, .post-content div:last-child p,
.post-content div:last-child ul, .post-content div:last-child ol,
.post-content div:last-child blockquote {
margin-bottom: 0;
}
.post-content h3 {
font: 20px Georgia,serif;
margin-bottom: 20px;
}
.post-content h3 a, .post-content h3 a:visited {
color: #111;
text-decoration: none;
}
.post-content h3 a:focus, .post-content h3 a:hover, .post-content h3:active {
color: {color:link hover};
}
.post-content img {
margin-bottom: 20px;
padding: 10px;
}
.post-type-photoset .post-content .photobox {
background: {color:content border};
margin-bottom: 20px;
padding: 5px;
}
.post-type-photoset .post-content .photobox img {
width: 245px;
margin: 0;
padding: 5px;
}
.photobox-one { /* 追加 */
display: inline-block;
}
.post-type-text .post-content ul {
padding-left: 30px;
}
.post-type-text .post-content ul ul {
margin-bottom: 0;
}
.post-type-text .post-content ul li {
list-style-type: disc;
}
.post-type-text .post-content ul ul li {
list-style-type: circle;
}
.post-type-text .post-content ol {
padding-left: 30px;
}
.post-type-text .post-content ol ol {
margin-bottom: 0;
}
.post-type-text .post-content ol li {
list-style-type: upper-latin;
}
.post-type-text .post-content ol ol li {
list-style-type: lower-latin;
}
.post-type-photoset .post-content .html_photoset {
background: {color:content border};
margin-bottom: 20px;
padding: 10px;
}
.post-type-photoset .post-content .html_photoset:focus, .post-type-photoset .post-content .html_photoset:hover, .post-type-photoset .post-content .html_photoset:active {
background: {color:link hover};
}/* 追加 */
.post-type-link .post-content .link-wrap {
margin-bottom: 20px;
}
.post-type-chat .post-content .label {
color: #333;
font-weight: bold;
}
.post-type-video .post-content .video-wrap {
background: {color:content border};
margin-bottom: 20px;
padding: 10px;
}
.post-type-video .post-content .video-wrap:focus, .post-type-video .post-content .video-wrap:hover, .post-type-video .post-content .video-wrap:active {
background: {color:link hover};
}/* 追加 */
.post-type-audio .post-content .caption {
margin-top: 10px;
}
.tags {
font-size: 13px;
}
.tags a {
text-decoration: none;
}
.tags a:after {
content: ",";
}
.tags a:last-child:after {
content: "";
}
#disqus_thread {
border-top: 1px solid #ccc;
padding: 10px 30px 0;
}
#disqus_thread h3 {
color: #111;
font: 18px Georgia,serif;
margin: 20px 0 10px;
}
#dsq-content .dsq-subscribe-menu {
font-size: 12px;
}
#post-notes {
border-top: 1px solid #ccc;
padding: 30px;
}
#post-notes ol li {
border-bottom: 1px dotted #ccc;
padding: 10px 0;
}
#post-notes ol li img {
background: none;
padding-right: 3px;
vertical-align: middle;
}
.pagination { /* "Home" のために変更 */
border-top: 1px solid #ccc;
overflow: hidden;
/* padding: 20px 0; */
padding: 20px 30px 20px 0;
}
/* .pagination .previous-page {
float: left;
}
.pagination .next-page {
float: right;
margin-right: 30px;
} */
.pagination ul {
display: flex;
justify-content: space-between;
margin: 0;
}
.pagination li {
display: inline-block;
}
.pagination a {
font: 20px Georgia,serif;
text-decoration: none;
visibility: hidden;
}
.pagination .visible {
visibility: visible;
}
#sidebar {
float: left;
padding-bottom: 30px;
width: 319px;
}
#sidebar h3 { /* .widgetにない項目はABOUTとかのもの*/
border-bottom: 1px dotted #ccc;
color: #999;
font-size: 14px;
font-weight: bold;
margin: 0 15px 20px 10px;
padding: 10px 10px; /* 9px 20px */
text-transform: uppercase;
}
#sidebar .widget h3 { /* 本文中のもの */
margin-right: 0px;
margin-left: 0px;
padding: 9px 10px;
}
#sidebar h3 a, #sidebar h3 a:visited {
color: #999;
text-decoration: none;
}
#sidebar h3 a:focus, #sidebar h3 a:hover, #sidebar h3 a:active {
color: {color:link hover};
}
#sidebar ul {
margin-bottom: 0;
margin-left: 1em; /* 追加 */
list-style: initial; /* 追加 */
}
.widget {
border-bottom: 1px solid #ccc;
color: #333;
font-size: 13px;
padding: 0 20px 20px 20px;
}
.widget h3 {
font: 20px Georgia,serif;
margin-bottom: 20px;
}
.widget h3 a, .widget h3 a:visited {
color: #000;
text-decoration: none;
}
.widget h3 a:focus, .widget h3 a:hover, .widget h3 a:active {
color: {color:link hover};
}
.widget img {
padding: 5px;
max-width: 250px;
}
.widget p:last-child, .widget ul:last-child, .widget ol:last-child, .widget blockquote:last-child {
margin-bottom: 0;
}
#about {
overflow: hidden;
}
#about img {
background: #fff;
border: 1px solid #ccc;
float: none;
margin-bottom: 0px;
padding: 3px;
}
#about a:focus img, #about a:hover img, #about a:active img {
border: 1px solid {color:link hover};
}
.like_post {
border-bottom: 1px dotted #ccc;
margin-bottom: 20px;
padding-bottom: 20px;
}
.like_post:last-child {
border: none;
margin: 0;
padding: 0;
}
.like_post ul {
padding-left: 20px;
}
.like_post ul ul {
margin-bottom: 0;
}
.like_post ul li {
list-style-type: disc;
}
.like_post ul ul li {
list-style-type: circle;
}
.like_post ol {
padding-left: 20px;
}
.like_post ol ol {
margin-bottom: 0;
}
.like_post ol li {
list-style-type: upper-latin;
}
.like_post ol ol li {
list-style-type: lower-latin;
}
.like_post p:last-child, .like_post ul:last-child, .like_post ol:last-child, .like_post blockquote:last-child {
margin-bottom: 0;
}
#tweets {
margin-bottom: 10px;
}
#tweets .content {
margin-bottom: 10px;
}
#tweets a {
text-decoration: none;
}
#following_container {
overflow: hidden;
padding-bottom: 20px;
}
#following_container li {
display: inline;
padding: 0;
margin: 0;
}
#footer {
border-top: 1px solid #ccc;
clear: both;
margin: 0 auto;
overflow: hidden;
width: 900px;
}
#colophon {
color: #555;
float: right;
font-size: 12px;
padding: 10px 0 20px;
}
#footer a {
border-bottom: 1px dotted #555;
text-decoration: none;
}
/* 以下追加 */
a, textarea {
word-break: break-all;
}
.description div {
margin-bottom: 20px;
}
.description div p {
margin-bottom: 10px;
}
{CustomCSS}
</style>
</head>
<body>
<div id="wrapper">
<div id="header">
<div id="access">
<div class="menu">
<div id="pages">
<ul>
<li><a href="/">Home</a></li>
{block:HasPages}{block:Pages}<li><a href="{URL}">{Label}</a></li>{/block:Pages}{/block:HasPages}
{block:AskEnabled}<li class="ask"><a href="/ask" class="page">{AskLabel}</a></li>{/block:AskEnabled}
{block:SubmissionsEnabled}<li class="submit"><a href="/submit" class="page">{SubmitLabel}</a></li>{/block:SubmissionsEnabled}
<li class="archive"><a href="/archive">Archive</a></li>
<li class="mobile"><a href="/mobile">Mobile</a></li>
<li class="rss"><a href="{RSS}">RSS</a></li>
</ul>
</div><!-- #pages -->
<div id="search">
<form action="/search" method="get">
<input type="text" name="q" value="{SearchQuery}"/>
<input type="submit" value="Search" class="search-button"/>
</form>
</div><!-- #search -->
</div><!-- .menu -->
</div><!-- #access -->
</div><!-- #header -->
<div id="main">
<div id="container">
<div id="content">
{block:Posts}
<div id="post-{PostID}" class="post {block:Text}post-type-text{/block:Text}{block:Photo}post-type-photo{/block:Photo}{block:Photoset}post-type-photoset{/block:Photoset}{block:Quote}post-type-quote{/block:Quote}{block:Link}post-type-link{/block:Link}{block:Chat}post-type-chat{/block:Chat}{block:Video}post-type-video{/block:Video}{block:Audio}post-type-audio{/block:Audio}">
<div class="post-meta">
<div class="type-date"> <!-- この辺から改造 -->
<a href="{BlogURL}post/{PostID}/">
<div class="type">
<!-- <a href="{ShortURL}"> -->{block:Text}Text{/block:Text}{block:Photo}Photo{/block:Photo}{block:Photoset}Photoset{/block:Photoset}{block:Quote}Quote{/block:Quote}{block:Link}Link{/block:Link}{block:Chat}Chat{/block:Chat}{block:Video}Video{/block:Video}{block:Audio}Audio{/block:Audio}<!-- </a> typeとdate全体にリンク張ることにした。ついでにURLの余計な本文パートを削除 -->
</div><!-- .type -->
{block:Date}
<div class="date">
{block:Japanese}
{Year}年{Month}{DayOfMonth}日
{/block:Japanese}
{block:NotJapanese}
{Month} {DayOfMonth}{DayOfMonthSuffix}, {Year}
{/block:NotJapanese}
</div><!-- .date -->
{/block:Date}
</a>
</div><!-- .type-date -->
{block:NoteCount}
<div class="note-count">
<a href="{Permalink}#post-notes">{NoteCountWithLabel}</a>
</div><!-- .note-count -->
{/block:NoteCount}
</div><!-- .post-meta -->
<div class="post-content">
{block:Text}
{block:Title}<h3><a href="{ShortURL}">{Title}</a></h3>{/block:Title}
{Body}
{/block:Text}
{block:Photo}
<a href="{PhotoURL-HighRes}" class="high-res" target="_blank"><img src="{PhotoURL-500}" class="photo" alt="{PhotoAlt}" /></a>
{block:Caption}<div class="caption">{Caption}</div>{/block:Caption}
{/block:Photo}
{block:Photoset}
<div class="photobox">
{block:Photos}<div class="photobox-one"><a href="{PhotoURL-HighRes}" class="high-res-photoset" target="_blank"><img src="{PhotoURL-250}" class="photo" alt="{PhotoAlt}" /></a></div>{/block:Photos}
</div>
{block:Caption}<div class="caption">{Caption}</div>{/block:Caption}
{/block:Photoset}
{block:Quote}
<div class="quote-content">"{Quote}"</div>
{block:Source}<p class="quote-source">&mdash; {Source}</p>{/block:Source}
{/block:Quote}
{block:Link}
<div class="link-wrap"><a href="{URL}" {Target}>{Name}</a></div>
{block:Description}<div class="description">{Description}</div>{/block:Description}
{/block:Link}
{block:Chat}
{block:Title}<h3><a href="{ShortURL}">{Title}</a></h3>{/block:Title}
<ul class="chat-wrap">
{block:Lines}
<li class="{Alt} user_{UserNumber}">
{block:Label}<span class="label">{Label}</span>{/block:Label}
{Line}
</li>
{/block:Lines}
</ul>
{/block:Chat}
{block:Video}
<div class="video-wrap">{Video-500}</div>
{block:Caption}<div class="caption">{Caption}</div>{/block:Caption}
{/block:Video}
{block:Audio}
<div class="audio-wrap">{AudioPlayerGrey}</div>
{block:Caption}<div class="caption">{Caption}</div>{/block:Caption}
{/block:Audio}
{block:HasTags}
<div class="tags">
<p>Tags: {block:Tags}<a href="{TagURL}" class="single-tag">{Tag}</a> {/block:Tags}</p>
</div>
{/block:HasTags}
</div><!-- post-content -->
</div><!-- .post -->
{block:PermalinkPagination}<!-- 追加 -->
<div class="pagination">
<ul>
<li><a {block:NextPost}class="visible" href="{NextPost}"{/block:NextPost}>&#171; New</a></li>
<li><a {block:PreviousPost}class="visible" href="{PreviousPost}"{/block:PreviousPost}>Old &#187;</a></li>
</ul>
</div>
{/block:PermalinkPagination}
{block:PostNotes}<div id="post-notes">{PostNotes}</div>{/block:PostNotes}
{/block:Posts}
{block:Pagination}
<div class="pagination"><!-- "Home" のために改造 -->
<ul>
<li><a {block:PreviousPage}class="visible" href="{PreviousPage}"{/block:PreviousPage}>&#171; New</a></li>
<li><a class="visible" href="/">Home</a></li>
<li><a {block:NextPage}class="visible" href="{NextPage}"{/block:NextPage}>Old &#187;</a></li>
</ul>
</div><!-- .pagination -->
{/block:Pagination}
</div><!-- #content -->
</div><!-- #container -->
<div id="sidebar">
<h3>About</h3>
<div id="about" class="widget">
<a href="/"><img src="{PortraitURL-64}" alt="portrait" /></a>
{block:Description}<div class="description"><p>{Description}</p></div>{/block:Description}
</div>
<!--
<form name="form1">
<textarea name="textarea1" rows="5" cols="40" onclick="this.select();"></textarea>
</form>
<script type="text/javascript">
const dbgg = v => { if (1) { console.log(v); } } // デバッグ時1に
dbgg('start unko');
let url = location.href;
let title = document.title;
// {blockk:PermalinkPage}
let caption = document.querySelector('.caption p:only-child, .caption p:not(:last-child)').innerHTML;
dbgg('最初: ' + caption);
const brPtn = String.raw`<br(?: */ *)?>`;
const aPtn = String.raw`<a [^>]+>(https?)://.+?</a>`;
const sPtn = String.raw`\s*`;
caption = caption.replace(
new RegExp(sPtn+brPtn+sPtn, 'g'),
' '
).replace(
new RegExp('^('+sPtn+aPtn+sPtn+')+'),
''
).replace(
new RegExp(sPtn+aPtn+sPtn, 'g'),
' *$1…* '
).replace(/\s+$/, '');
dbgg('置換後: ' + caption);
// n文字以上なら頭からn文字だけ切り出して尻に「...」とでも付ける処理
dbgg('切出後: ' + caption);
title = '"' + caption + '" | {Title}';
const urlPtn = String.raw`^({BlogURL}post/\d+).+$`;
url = url.replace(new RegExp(urlPtn), '$1/');
// {/blockk:PermalinkPage}
const titleAndUrl = title + '\r' + url;
document.form1.textarea1.value = titleAndUrl;
dbgg('end unko');
</script>
-->
</div><!-- #sidebar -->
</div><!-- #main -->
<div id="footer">
<div id="colophon"><p>Powered by <a href="http://tumblr.com" target="_blank" rel="noopener noreferrer">Tumblr</a>. <a href="http://www.tumblr.com/theme/10375" target="_blank" rel="noopener noreferrer">Minimal Theme</a> designed by <a href="http://arturkim.com" target="_blank" rel="noopener noreferrer">Artur Kim</a>. 改造 by <a href="http://phroneris.com" target="_blank" rel="noopener noreferrer">森の子リスのミーコの大冒険(Phroneris)</a>.</p></div>
</div><!-- #footer -->
</div><!-- #wrapper -->
<!--
<script type="text/javascript">
const debug = v => { console.log(v); }
const a = 'abc';
debug(`a1: ` + a); // (OK)
debug(`a2: ${a}`); // (NG)
debug(String.raw`a\z3: ` + a); // (OK)
debug(String.raw`a
4: ` + a); // (NG)
</script>
-->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://unpkg.com/xregexp/xregexp-all.js"></script>
<!-- IDとハッシュタグの自動リンク化 -->
<script type="text/javascript">
'use strict';
const dbg = v => { if (0) { console.log(v); } } // デバッグ時1に
dbg('▼▼▼==================== START UNKO ====================▼▼▼');
const iStr = i => '{{unko' + (('000'+i).slice(-3)) + '}}'; // 0埋めしたaタグ置換用文字列
const pLM = String.raw`\pL\pM\u037f\u0528-\u052f\u08a0-\u08b2\u08e4-\u08ff\u0978\u0980\u0c00\u0c34\u0c81\u0d01\u0ede\u0edf\u10c7\u10cd\u10fd-\u10ff\u16f1-\u16f8\u17b4\u17b5\u191d\u191e\u1ab0-\u1abe\u1bab-\u1bad\u1bba-\u1bbf\u1cf3-\u1cf6\u1cf8\u1cf9\u1de7-\u1df5\u2cf2\u2cf3\u2d27\u2d2d\u2d66\u2d67\u9fcc\ua674-\ua67b\ua698-\ua69d\ua69f\ua792-\ua79f\ua7aa-\ua7ad\ua7b0\ua7b1\ua7f7-\ua7f9\ua9e0-\ua9ef\ua9fa-\ua9fe\uaa7c-\uaa7f\uaae0-\uaaef\uaaf2-\uaaf6\uab30-\uab5a\uab5c-\uab5f\uab64\uab65\uf870-\uf87f\uf882\uf884-\uf89f\uf8b8\uf8c1-\uf8d6\ufa2e\ufa2f\ufe27-\ufe2d\ud800\udee0\ud800\udf1f\ud800\udf50-\ud800\udf7a\ud801\udd00-\ud801\udd27\ud801\udd30-\ud801\udd63\ud801\ude00-\ud801\udf36\ud801\udf40-\ud801\udf55\ud801\udf60-\ud801\udf67\ud802\udc60-\ud802\udc76\ud802\udc80-\ud802\udc9e\ud802\udd80-\ud802\uddb7\ud802\uddbe\ud802\uddbf\ud802\ude80-\ud802\ude9c\ud802\udec0-\ud802\udec7\ud802\udec9-\ud802\udee6\ud802\udf80-\ud802\udf91\ud804\udc7f\ud804\udcd0-\ud804\udce8\ud804\udd00-\ud804\udd34\ud804\udd50-\ud804\udd73\ud804\udd76\ud804\udd80-\ud804\uddc4\ud804\uddda\ud804\ude00-\ud804\ude11\ud804\ude13-\ud804\ude37\ud804\udeb0-\ud804\udeea\ud804\udf01-\ud804\udf03\ud804\udf05-\ud804\udf0c\ud804\udf0f\ud804\udf10\ud804\udf13-\ud804\udf28\ud804\udf2a-\ud804\udf30\ud804\udf32\ud804\udf33\ud804\udf35-\ud804\udf39\ud804\udf3c-\ud804\udf44\ud804\udf47\ud804\udf48\ud804\udf4b-\ud804\udf4d\ud804\udf57\ud804\udf5d-\ud804\udf63\ud804\udf66-\ud804\udf6c\ud804\udf70-\ud804\udf74\ud805\udc80-\ud805\udcc5\ud805\udcc7\ud805\udd80-\ud805\uddb5\ud805\uddb8-\ud805\uddc0\ud805\ude00-\ud805\ude40\ud805\ude44\ud805\ude80-\ud805\udeb7\ud806\udca0-\ud806\udcdf\ud806\udcff\ud806\udec0-\ud806\udef8\ud808\udf6f-\ud808\udf98\ud81a\ude40-\ud81a\ude5e\ud81a\uded0-\ud81a\udeed\ud81a\udef0-\ud81a\udef4\ud81a\udf00-\ud81a\udf36\ud81a\udf40-\ud81a\udf43\ud81a\udf63-\ud81a\udf77\ud81a\udf7d-\ud81a\udf8f\ud81b\udf00-\ud81b\udf44\ud81b\udf50-\ud81b\udf7e\ud81b\udf8f-\ud81b\udf9f\ud82f\udc00-\ud82f\udc6a\ud82f\udc70-\ud82f\udc7c\ud82f\udc80-\ud82f\udc88\ud82f\udc90-\ud82f\udc99\ud82f\udc9d\ud82f\udc9e\ud83a\udc00-\ud83a\udcc4\ud83a\udcd0-\ud83a\udcd6\ud83b\ude00-\ud83b\ude03\ud83b\ude05-\ud83b\ude1f\ud83b\ude21\ud83b\ude22\ud83b\ude24\ud83b\ude27\ud83b\ude29-\ud83b\ude32\ud83b\ude34-\ud83b\ude37\ud83b\ude39\ud83b\ude3b\ud83b\ude42\ud83b\ude47\ud83b\ude49\ud83b\ude4b\ud83b\ude4d-\ud83b\ude4f\ud83b\ude51\ud83b\ude52\ud83b\ude54\ud83b\ude57\ud83b\ude59\ud83b\ude5b\ud83b\ude5d\ud83b\ude5f\ud83b\ude61\ud83b\ude62\ud83b\ude64\ud83b\ude67-\ud83b\ude6a\ud83b\ude6c-\ud83b\ude72\ud83b\ude74-\ud83b\ude77\ud83b\ude79-\ud83b\ude7c\ud83b\ude7e\ud83b\ude80-\ud83b\ude89\ud83b\ude8b-\ud83b\ude9b\ud83b\udea1-\ud83b\udea3\ud83b\udea5-\ud83b\udea9\ud83b\udeab-\ud83b\udebb`;
const pN = String.raw`\pNd\u0de6-\u0def\ua9f0-\ua9f9\ud804\udcf0-\ud804\udcf9\ud804\udd36-\ud804\udd3f\ud804\uddd0-\ud804\uddd9\ud804\udef0-\ud804\udef9\ud805\udcd0-\ud805\udcd9\ud805\ude50-\ud805\ude59\ud805\udec0-\ud805\udec9\ud806\udce0-\ud806\udce9\ud81a\ude60-\ud81a\ude69\ud81a\udf50-\ud81a\udf59`;
const pS = String.raw`_\u200c\u200d\ua67e\u05be\u05f3\u05f4\uff5e\u301c\u309b\u309c\u30a0\u30fb\u3003\u0f0b\u0f0c\u00b7`;
// pLM: Letters and Marks, pN: Numerals, pS: Special characters
const pLMNS = pLM + pN + pS;
const tagPtn = '(^|\\uFE0E|\\uFE0F|[^&'+pLMNS+'])(#|\\uFF03)(?!\\uFE0F|\\u20E3)(['+pLMNS+']*['+pLM+']['+pLMNS+']*)';
dbg('tagPtn: ' + tagPtn);
const tagPtnX = XRegExp(tagPtn, 'giu');
// tagPtn $1:直前, $2:#, ?!:始められない文字, $3:タグの中身
const pA = String.raw`@\uFF20`;
// pA: At signs
const idPtn = '([^a-z0-9_!#$%&*'+pA+']|^|(?:^|[^a-z0-9_+~.-])RT:?)(['+pA+']+)([a-z0-9_]{1,20})'
dbg('idPtn: ' + idPtn);
// idPtn $1:直前, $2:@, $3:IDの中身
$('.caption p').each(function(){
let str = $(this).html();
let i = 0, elems = [];
dbg('★--- $(".caption p") FOUND! ---★');
dbg('str_original : ' + str);
$('a', this).each(function(){
// TumblrによるURLの自動リンクは残したい(URL内の@や#まで置換したくない)ので避難
// 子でない部分だけをもっとスマートに選択したかったが方法は無かった
const e = $(this).prop('outerHTML');
dbg(iStr(i) + ' : ' + e);
elems.push(e);
str = str.replace(e, iStr(i));
i++;
});
dbg('str_replaced : ' + str);
// dbg(elems);
str = XRegExp.replace(
str,
tagPtnX,
(match, pre, igeta, tag, offset, string) => {
dbg('* tag - 直前: "' + encodeURI(pre) + '", #: "' + igeta + '", 中身: "' + tag + '"');
return [pre, '<a href="https://twitter.com/search?q=%23', encodeURI(tag), '">', igeta, tag, '</a>'].join('');
}
)
.replace(
new RegExp(idPtn, "gi"),
(match, pre, at, id, offset, string) => {
dbg('* ID - 直前: "' + encodeURI(pre) + '", @: "' + at + '", 中身: "' + id + '"');
return [pre, '<a href="https://twitter.com/', id, '">', at, id, '</a>'].join('');
}
);
while(i--){
str = str.replace(iStr(i), elems[i]);
}
// ついでに自動リンクを強制新規タブ化し、
// Tumblr側の新規タブ化設定では追加されないrel属性を追加
str = str.replace(
/(?:target|rel|title)=".+?"/g,
''
).replace(
/<a +/g,
'<a target="_blank" rel="noopener noreferrer" title="{block:Japanese}新規タブで開く{/block:Japanese}{block:NotJapanese}Open in new tab{/block:NotJapanese}" '
);
dbg('str_final : ' + str);
$(this).html(str);
});
dbg('▲▲▲==================== END UNKO ====================▲▲▲');
/*
★ ハッシュタグ検出の正規表現についての細かいこと
実装経緯はこんなん。
2018/10/04 「CODE Q&A 問題解決」とかいう雑な機械翻訳転載サイトで具体的な正規表現指定を知る。
* 最高のHashTag正規表現 [regex] [twitter] | CODE Q&A 問題解決 [日本語]
https://code.i-harness.com/ja/q/17dcc4
2018/10/06 JSの正規表現ではUnicode文字プロパティが使えず、またjQueryとXRegExpが併用できないと思って、地獄の生クラスで無理やり実装。
2019/01/25 XRegExpを導入して元のままの人権ある表記にする。
2019/03/15 記事のサイトがなぜかDIYの素材解説サイトに生まれ変わってて、元のコンテンツが軒並み死んだ(Web Archiveも無い)のを知る。
2019/12/07 よく考えたら上記の経緯メモから日本語記事名はわかるので、そこから目星をつけて割とあっさり元記事を見つける。
* .net - Best HashTag Regex - Stack Overflow
https://stackoverflow.com/questions/1563844/best-hashtag-regex
ついでに、いつからかエラーで死んでたのを修正。正規表現中の&と#を過保護にエスケープしていたのがかえって駄目だった模様。
あとなんか機械翻訳サイトがまた同じ方向性で復活してたけど、元通りというわけでは全然ないのであの記事は変わらず見れない。もう見る必要もないが。
2019/12/09 ソースをGistに保存することにして、それまでソースコード内に直書きされ積み重なっていた過去ログ(?)のスリム化を狙う。
2019/12/10 言うて元記事も少し古い情報だったので、内容を最新のソース(2018/10/11コミット)に追従。
* https://github.com/twitter/twitter-text/blob/master/java/src/main/java/com/twitter/twittertext/Regex.java
なお、Twitter公式がなぜ\p{}式の手っ取り早いUnicode文字プロパティを使わないかについては、以下に書かれている。
* https://github.com/twitter/twitter-text/tree/master/unicode_regex
要は環境次第で対応文字の実装がまちまちだからか。
★ 波括弧について
Unicode文字プロパティを使う際、波括弧を扱うには頑張る必要がある。
* \\p\{L\} : 地道にエスケープする
* \\pL : 波括弧無しの短縮表記を使う
どのみち頭のバックスラッシュに大量のエスケープが必要となりめんどいので、以下の記事のようなテンプレートリテラル String.raw`` を利用した。
* JavaScript の テンプレートリテラル を極める! - Qiita
https://qiita.com/kura07/items/c9fa858870ad56dfec12
また、テンプレートリテラルの ${} による変数展開も使えない。
この辺はXRegExpどうこうというより、Tumblr側の問題のように思う。
不便だから早く使えるようにしてほしい。
★ 他、役立ったサイト
* Unicode Utilities: UnicodeSet
https://unicode.org/cldr/utility/list-unicodeset.jsp
* RegexPlanet: online regular expression testing for XRegExp
http://www.regexplanet.com/advanced/xregexp/index.html
*/
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment