Last active
September 8, 2019 09:26
-
-
Save aiya000/801bec5a9b869eb70f30dcb1660898ba to your computer and use it in GitHub Desktop.
会話風「キャラクター + ふきだし」 in Re:VIEW css-typesetting https://gyazo.com/163677e435eef1bcac18ca034dc1112e
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@media print { | |
body { | |
font-family: 'Noto Sans CJK JP', sans-serif; | |
} | |
/* @import url(https://fonts.googleapis.com/earlyaccess/notosansjp.css); */ | |
/* | |
* Noto Sans (japanese) http://www.google.com/fonts/earlyaccess | |
*/ | |
@font-face { | |
font-family: 'Noto Sans CJK JP'; | |
font-style: normal; | |
font-weight: 100; | |
src: local("Noto Sans CJK JP Thin"), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Thin.woff2) format('woff2'), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Thin.woff) format('woff'), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Thin.otf) format('opentype'); | |
} | |
@font-face { | |
font-family: 'Noto Sans CJK JP'; | |
font-style: normal; | |
font-weight: 300; | |
src: local("Noto Sans CJK JP Light"), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Light.woff2) format('woff2'), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Light.woff) format('woff'), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Light.otf) format('opentype'); | |
} | |
@font-face { | |
font-family: 'Noto Sans CJK JP'; | |
font-style: normal; | |
font-weight: 400; | |
src: local("Noto Sans CJK JP Regular"), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Regular.woff2) format('woff2'), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Regular.woff) format('woff'), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Regular.otf) format('opentype'); | |
} | |
@font-face { | |
font-family: 'Noto Sans CJK JP'; | |
font-style: normal; | |
font-weight: 500; | |
src: local("Noto Sans CJK JP Medium"), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Medium.woff2) format('woff2'), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Medium.woff) format('woff'), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Medium.otf) format('opentype'); | |
} | |
@font-face { | |
font-family: 'Noto Sans CJK JP'; | |
font-style: normal; | |
font-weight: 700; | |
src: local("Noto Sans CJK JP Bold"), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Bold.woff2) format('woff2'), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Bold.woff) format('woff'), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Bold.otf) format('opentype'); | |
} | |
@font-face { | |
font-family: 'Noto Sans CJK JP'; | |
font-style: normal; | |
font-weight: 900; | |
src: local("Noto Sans CJK JP Black"), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Black.woff2) format('woff2'), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Black.woff) format('woff'), | |
url(https://fonts.gstatic.com/ea/notosansjp/v5/NotoSansJP-Black.otf) format('opentype'); | |
} | |
} | |
body { | |
page-break-before: left; | |
counter-reset: footnote; | |
} | |
@media screen { | |
:root { | |
line-height: 1.3; | |
} | |
.print-only { | |
display: none; | |
} | |
} | |
@media print { | |
:root { | |
font-weight: 400; | |
line-height: 1.5; | |
padding-top: 1.5rem; | |
} | |
/* A5設定 */ | |
:root { | |
font-size: 9pt; | |
} | |
a { | |
text-decoration: none; | |
font-style: italic; | |
} | |
a:link, | |
a:visited { | |
color: black; | |
} | |
} | |
@media print { | |
.titlepage-page > .titlepage { | |
text-align: center; | |
} | |
} | |
.titlepage-page > .titlepage > h1 { | |
font-size: 2.5rem; | |
} | |
.titlepage-page > .titlepage > .author { | |
font-size: 2rem; | |
} | |
.titlepage-page > .titlepage > .illustrator { | |
font-size: 2rem; | |
} | |
@media print { | |
.colophon-page > .colophon { | |
text-align: right; | |
} | |
} | |
.colophon-page > .colophon > h1 { | |
font-size: 1.8rem; | |
} | |
.colophon-page > .colophon > hr { | |
width: 50%; | |
margin-right: 0; | |
border: 1px solid black; | |
} | |
section { | |
break-before: page; | |
break-after: page; | |
} | |
nav { | |
break-before: page; | |
break-after: page; | |
} | |
aside { | |
break-before: page; | |
break-after: page; | |
} | |
p.footnote { | |
float: footnote; | |
} | |
a.noteref { | |
vertical-align: super; | |
} | |
/* NOTE footnoteの自動採番がやりたかった奴〜〜 */ | |
/* | |
section { | |
counter-reset: footnote; | |
} | |
p.footnote { | |
counter-increment: footnote; | |
} | |
p.footnote::footnote-marker { | |
content: '* ' counter(footnote); | |
} | |
a.noteref::before { | |
content: '*' target-counter(attr(href), footnote); | |
vertical-align: super; | |
} | |
*/ | |
nav.toc a::after { | |
content: target-counter(attr(href), page); | |
float: right; | |
} | |
p { | |
text-indent: 1rem; | |
text-align: justify; | |
margin-top: 0.3rem; | |
margin-bottom: 0; | |
} | |
/* .image, */ | |
p.caption { | |
text-align: center; | |
text-indent: 0; | |
} | |
/* list, emlist, tableのキャプションは左寄せ */ | |
.caption-code p.caption, | |
.emlist-code p.caption { | |
text-align: start; | |
} | |
p.caption::before { | |
color: gray; | |
content: "▲"; | |
} | |
.caption-code p.caption::before, | |
.emlist-code p.caption::before, | |
.table p.caption::before { | |
color: gray; | |
content: "▲"; | |
} | |
pre.cmd { | |
font-size: 0.8rem; | |
background-color: #444; | |
color: white; | |
padding: 1rem 2rem; | |
} | |
pre.list, pre.emlist { | |
font-family: 'Noto Sans Mono CJK JP', monospace; /* :D */ | |
padding: 1rem 2rem; | |
background-color: #eee; | |
border: solid 3px gray; | |
border-radius: 0.3rem; | |
} | |
table { | |
margin: 0 auto 2em auto; | |
border-collapse: collapse; | |
} | |
table tr th { | |
border: 1px black solid; | |
font-size: 0.9rem; | |
padding: 0.3rem; | |
} | |
table tr td { | |
border:1px black solid; | |
font-size: 0.9rem; | |
padding: 0.3rem; | |
} | |
p.tablecaption, table caption { | |
color: #666; | |
font-weight: bold; | |
text-indent: 0; | |
} | |
div.image { | |
text-align: center; | |
} | |
div.column { | |
margin: 10px; | |
padding: 0.8rem 1.5rem; | |
border: solid 3px gray; | |
border-radius: 0.3rem; | |
} | |
div.column h4 { | |
margin-top: 0; | |
} | |
/* ブロック系の途中で改ページされるのを避ける。本当はかかってもいいんだけど脚注がある時に背景がぶっ壊れる… */ | |
pre.cmd { | |
page-break-inside: avoid; | |
} | |
pre.list, pre.emlist { | |
page-break-inside: avoid; | |
} | |
table { | |
page-break-inside: avoid; | |
} | |
@page { | |
size: B5; | |
/* トンボ */ | |
/* marks: crop cross; */ | |
/* 裁ち落としのとこまで塗りたかったら pentapod本を トンボ で検索 */ | |
} | |
@page { | |
margin: 10mm; | |
margin-top: 15mm; | |
} | |
/* A4設定 */ | |
/* | |
@page :left { | |
margin-left: 30mm; | |
padding: 1rem; | |
} | |
@page :right { | |
margin-right: 30mm; | |
padding: 1rem; | |
} | |
*/ | |
/* A5設定 */ | |
@page :left { | |
margin-left: 15mm; | |
padding: 1rem; | |
} | |
@page :right { | |
margin-right: 15mm; | |
padding: 1rem; | |
} | |
@page :left { | |
@top-left { | |
/* 本当は現在の深さ1の見出しを出したい */ | |
/* かつ、sectionの1ページ目だったら出したくない */ | |
content: "せつラボ"; | |
vertical-align: bottom; | |
border-bottom: solid 1px black; | |
} | |
@top-right { | |
content: " "; /* 内容ないと枠でない */ | |
border-bottom: solid 1px black; | |
} | |
@top-center { | |
content: " "; /* 内容ないと枠でない */ | |
border-bottom: solid 1px black; | |
} | |
@bottom-center { | |
content: "←" counter(page); | |
} | |
} | |
@page :right { | |
@top-right { | |
/* 本当は現在の深さ2の見出しを出したい */ | |
/* かつ、sectionの1ページ目だったら出したくない */ | |
content: "せつラボ"; | |
vertical-align: bottom; | |
border-bottom: solid 1px black; | |
} | |
@top-left { | |
content: " "; /* 内容ないと枠でない */ | |
border-bottom: solid 1px black; | |
} | |
@top-center { | |
content: " "; /* 内容ないと枠でない */ | |
border-bottom: solid 1px black; | |
} | |
@bottom-center { | |
content: counter(page) "→"; | |
} | |
} | |
/* NOTE これイケるのでは?と思ったけどダメだった | |
@page foobar:right { | |
@top-right { | |
content: "章タイトルだよー"; | |
} | |
} | |
section.foobar { | |
page: foobar; | |
} | |
*/ | |
/* NOTE これもイケるのでは?と思ったけどサポートされてなさそう | |
@page :right { | |
@top-right { | |
content: element(chaptitle); | |
} | |
} | |
section h1 { | |
position: running(chaptitle); | |
} | |
*/ | |
@page :first { | |
padding-top: 0mm; | |
} | |
/* 1ページ目は扉なのでページ上部の装飾無し */ | |
@page :first { | |
@top-right { | |
content: " "; | |
border-bottom: none; | |
} | |
@top-left { | |
content: " "; | |
border-bottom: none; | |
} | |
@top-center { | |
content: " "; | |
border-bottom: none; | |
} | |
} | |
/* TODO 最終ページは奥付なのでページ上部の装飾無し */ | |
/* …はてどうやるんだ??名前付きページはまだサポートされてなさそう… */ | |
/* | |
section.colophon-page { | |
page: colophon; | |
} | |
@page colophon { | |
@top-right { | |
content: " "; | |
border-bottom: none; | |
} | |
@top-left { | |
content: " "; | |
border-bottom: none; | |
} | |
@top-center { | |
content: " "; | |
border-bottom: none; | |
} | |
} | |
*/ | |
.width-010per { width: 10%; } | |
.width-020per { width: 20%; } | |
.width-025per { width: 25%; } | |
.width-030per { width: 30%; } | |
.width-033per { width: 33%; } | |
.width-040per { width: 40%; } | |
.width-050per { width: 50%; } | |
.width-060per { width: 60%; } | |
.width-067per { width: 67%; } | |
.width-070per { width: 70%; } | |
.width-075per { width: 75%; } | |
.width-080per { width: 80%; } | |
.width-090per { width: 90%; } | |
.width-100per { width: 100%; } | |
/* It's me, aiya000 :D */ | |
.book-toc li { | |
list-style: none; | |
} | |
.child-chapter { | |
list-style: none; | |
} | |
.inline-code { | |
font-family: 'Noto Sans Mono CJK JP'; | |
} | |
/* review-ext.rb */ | |
.talk-left { | |
width: 100%; | |
margin: 10px; | |
overflow: hidden; | |
} | |
.talk-left-speaker { | |
display: inline-block; | |
vertical-align: top; | |
} | |
.talk-left-speaker img { | |
width: 2.0cm; | |
} | |
.talk-left-sentence { | |
display: inline-block; | |
position: relative; | |
padding: 10px; | |
margin: 0 0 0 10px; | |
border-radius: 12px; | |
background: whitesmoke; | |
max-width: 65%; | |
} | |
.talk-left-sentence:after { | |
content: ""; | |
position: absolute; | |
top: 15px; | |
left: -19px; | |
border: 8px solid transparent; | |
border-right: 18px solid whitesmoke; | |
transform: rotate(-15deg); | |
} | |
.talk-left-sentence p { | |
padding: 1.5px 0 1.5px 0; | |
text-indent: 0; | |
} | |
.talk-left-sentence-desc p { | |
text-indent: 10px; | |
} | |
.talk-right { | |
width: 100%; | |
margin: 10px; | |
overflow: hidden; | |
text-align: right; | |
} | |
.talk-right-sentence { | |
display: inline-block; | |
position: relative; | |
padding: 10px; | |
margin: 0 10px 0 0; | |
border-radius: 12px; | |
background: whitesmoke; | |
max-width: 65%; | |
text-align: left; | |
} | |
.talk-right-sentence:after { | |
content: ""; | |
position: absolute; | |
top: 15px; | |
right: -19px; | |
border: 8px solid transparent; | |
border-left: 18px solid whitesmoke; | |
transform: rotate(15deg); | |
} | |
.talk-right-sentence p { | |
padding: 1.5px 0 1.5px 0; | |
text-indent: 0; | |
} | |
.talk-right-sentence-desc p { | |
text-indent: 10px; | |
} | |
.talk-right-speaker { | |
display: inline-block; | |
vertical-align: top; | |
} | |
.talk-right-speaker img { | |
width: 2.0cm; | |
} | |
.attention { | |
padding: 10px 0; | |
} | |
.attention-line { | |
text-align: center; | |
} | |
.romanlist { | |
counter-reset: list; | |
margin: 16px 0 16px -4px; /* this margin-left fixes a difference between this and '*' '1.' list */ | |
border: solid 1px whitesmoke; | |
} | |
.romanlist li { | |
list-style: none; | |
margin: 2px 4px; | |
} | |
.romanlist li:before { | |
content: counter(list) ") "; | |
counter-increment: list; | |
} | |
.character-intro { | |
position: relative; | |
filter: grayscale(100%); | |
} | |
.character-intro img { | |
position: absolute; | |
top: 0; | |
right: 0; | |
width: 128px; | |
height: 128px; | |
border-radius: 10px; | |
border: solid 1px black; | |
} | |
.focus { | |
text-align: center; | |
} | |
.picture { | |
margin: 1.1cm; | |
padding: 0.1cm; | |
border: solid 1px black; | |
} | |
.picture img { | |
width: 100%; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: utf-8 | |
ReVIEW::Compiler.defblock :talkleft, 1 | |
ReVIEW::Compiler.defblock :talkright, 1 | |
ReVIEW::Compiler.defblock :attention, 0 | |
ReVIEW::Compiler.defblock :romanlist, 0 | |
ReVIEW::Compiler.defblock :charintro, 1 | |
ReVIEW::Compiler.defblock :list, 3 | |
ReVIEW::Compiler.defsingle :focus, 0..1 | |
ReVIEW::Compiler.definline :mathcode | |
ReVIEW::Compiler.definline :rubycode | |
module ReVIEW | |
class HTMLBuilder | |
# LINEっぽく、アイコンがしゃべってるみたいに、 | |
# セリフ内容を吹き出しで囲うやつ。 | |
# | |
# η専用。 | |
# 空行に区切られた各文節を<p></p>する。 | |
# | |
# linesが2行以上場合はηの口調が説明的であるので、字下げをオンにして見やすくするよ。 | |
# (1行のみのセリフを字下げすると、時差現が変な左の空白に見えるため) | |
def talkleft(lines, who) | |
speaker = | |
case who | |
# srcは64pxの画像 | |
when 'eta' | |
{alt: 'η', src: 'images/eta.png'} | |
when 'eta-arms' | |
{alt: 'η∞', src: 'images/eta-arms.png'} | |
when 'eta-sure' | |
{alt: 'η:)', src: 'images/eta-sure.png'} | |
when 'eta-smile' | |
{alt: 'η=)', src: 'images/eta-smile.png'} | |
when 'eta-light' | |
{alt: 'η=D', src: 'images/eta-light.png'} | |
when 'eta-thinking' | |
{alt: 'η:(', src: 'images/eta-thinking.png'} | |
when 'eta-blushed' | |
{alt: 'η…', src: 'images/eta-blushed.png'} | |
when 'eta-waver' | |
{alt: 'η…💦', src: 'images/eta-waver.png'} | |
when 'eta-waver-very' | |
{alt: 'η…💦💦', src: 'images/eta-waver-very.png'} | |
when 'invisible' | |
# 演出等に、アイコンを出したくない時など | |
{alt: '', src: ''} | |
else | |
raise "an unknown lefty speaker '#{who}'" | |
end | |
# TODO: 「行が2行以上」じゃなくて「\n\n」を確認する。(節が2つ以上) | |
talk_left_sentence_desc = -> (child){ | |
if lines.length >= 2 then | |
%Q(<div class="talk-left-sentence-desc">#{child}</div>) | |
else | |
child | |
end | |
} | |
sentence = insert_space_after_japanese_punctuation( | |
talk_left_sentence_desc.(make_talk_sentence(lines)) | |
) | |
puts <<~EOS | |
<div class="talk-left"> | |
<div class="talk-left-speaker"> | |
<img alt="#{speaker[:alt]}" src="#{speaker[:src]}"/> | |
</div> | |
<div class="talk-left-sentence"> | |
#{sentence} | |
</div> | |
</div> | |
EOS | |
end | |
# talkleftと同じだけど、η以外。 | |
def talkright(lines, who) | |
speaker = | |
case who | |
when 'mu' | |
{alt: 'μ', src: 'images/mu.png'} | |
when 'mu-saying' | |
{alt: 'μ「」', src: 'images/mu-saying.png'} | |
when 'mu-love' | |
{alt: 'μ//', src: 'images/mu-love.png'} | |
when 'mu-heart' | |
{alt: 'μ♡', src: 'images/mu-heart.png'} | |
when 'mu-wink' | |
{alt: 'μ;)', src: 'images/mu-wink.png'} | |
when 'mu-note' | |
{alt: 'μ♪', src: 'images/mu-note.png'} | |
when 'mu-smile' | |
{alt: 'μ:)', src: 'images/mu-smile.png'} | |
when 'mu-question' | |
{alt: 'μ?', src: 'images/mu-question.png'} | |
when 'somebody' | |
# 現時点では誰が発声したのかわからない時など | |
{alt: '', src: ''} | |
else | |
raise "an unknown rightly speaker '#{who}'" | |
end | |
talk_right_sentence_desc = -> (child){ | |
if lines.length >= 2 then | |
%Q(<div class="talk-right-sentence-desc">#{child}</div>) | |
else | |
child | |
end | |
} | |
sentence = insert_space_after_japanese_punctuation( | |
talk_right_sentence_desc.(make_talk_sentence(lines)) | |
) | |
puts <<~EOS | |
<div class="talk-right"> | |
<div class="talk-right-sentence"> | |
#{sentence} | |
</div> | |
<div class="talk-right-speaker"> | |
<img alt="#{speaker[:alt]}" src="#{speaker[:src]}"/> | |
</div> | |
</div> | |
EOS | |
end | |
# @param [string] pos 'left' or 'right' | |
# @param [{alt: string, src: string}] speaker an img | |
# | |
# >>> make_talk_sentence(['ああ、', 'うん。', '', 'そう。']) | |
# "<div>ああ、うん。</div><div>そう。</div>" | |
private def make_talk_sentence(lines) | |
clauses = splitBy(lines, ->(x){ x == '' }).map {|clause| | |
clause.join | |
} | |
clauses.map {|clause| | |
"<p>#{clause}</p>" | |
}.join | |
end | |
# @param [array of T] xs | |
# @param [T -> bool] p a predicate for xs | |
# | |
# >>> p splitBy([10, 20, 0, 10, 0, 20], ->(x){ x == 0 }) | |
# [[10, 20], [10], [20]] | |
private def splitBy(xs, p) | |
result = [] | |
child = [] | |
for x in xs do | |
if p.(x) then | |
result += [child] | |
child = [] | |
else | |
child += [x] | |
end | |
end | |
result += [child] | |
result | |
end | |
def attention(lines) | |
children = lines.map {|line| | |
%Q(<p class="attention-line">#{line}</p>) | |
} | |
puts %Q(<div class="attention">#{children.join}</div>) | |
end | |
def romanlist(lines) | |
list_items = lines.map {|line| | |
%Q(<li>#{line}</li>) | |
} | |
puts %Q(<ul class="romanlist">#{list_items.join}</ul>) | |
end | |
def charintro(lines, image_path) | |
sentence = lines.map {|line| | |
%Q(<p>#{line}</p>) | |
}.join | |
puts %Q( | |
<div class="character-intro"> | |
<div>#{sentence}</div> | |
<img src="#{image_path}" alt="キャラクターアイコン" /> | |
</div> | |
) | |
end | |
def list(lines, id, caption, lang = nil) | |
puts %Q(<div id="#{normalize_id(id)}" class="caption-code">) | |
math_lines = lines.map {|line| mathematical_code(line)} | |
list_body id, math_lines, lang | |
begin | |
list_header id, caption, lang | |
rescue KeyError | |
error "no such list: #{id}" | |
end | |
puts '</div>' | |
end | |
# ηの考え事が中心の章から、μとの会話が中心の章へ移る時に、 | |
# 後者の章の冒頭に入れるやつ。 | |
def focus(symbol = '◆') | |
puts %Q(<p class="focus">#{symbol} #{symbol} #{symbol}</p>) | |
end | |
# A kind of `code`. | |
# Regards a suffix number to a sup | |
def inline_mathcode(s) | |
%Q(<code class="inline-code tt">#{mathematical_code(s)}</code>) | |
end | |
def inline_rubycode(s) | |
%Q(<code class="inline-code tt">#{inline_ruby(s)}</code></ruby>) | |
end | |
# # footnoteの採番をブラウザでやらせようとして挫折 | |
# # vivliostyle.jsがIDを書き換えてしまい、参照できなくなってしまう | |
# # target-counter を使ったやりかた | |
# def footnote(id, str) | |
# puts %Q(<p class="footnote" id="fn-#{normalize_id(id)}"> | |
# <span>#{compile_inline(str)}</span></p>) | |
# end | |
# def inline_fn(id) | |
# # 番号はCSSで出すので気にしない | |
# %Q(<a id="fnb-#{normalize_id(id)}" href="#fn-#{normalize_id(id)}" | |
# class="noteref"><!--#{@chapter.footnote(id).number}--></a>) | |
# end | |
end | |
module BuilderOverride | |
Compiler.definline :bruby | |
def inline_bruby(s) | |
"<b>#{inline_ruby(s)}</b>" | |
end | |
end | |
class Builder | |
prepend BuilderOverride | |
end | |
end | |
def insert_space_after_japanese_punctuation(sentence) | |
punctuations = '!?♪' | |
sentence.gsub(/([#{punctuations}])([^\s 」』…#{punctuations}])/, '\1 \2') | |
end | |
def mathematical_code(s) | |
names = '[A-Za-zαβγδεζηθικλμνξοπρστυφχψω≦≧<>]' | |
indice = '[0-9a-zA-Z\-,]' | |
mathematical = s.gsub(/(#{names})_(#{indice})/, '\1<sub>\2</sub>') | |
mathematical = mathematical.gsub(/(#{names})\^(#{indice})/, '\1<sup>\2</sup>') | |
mathematical = mathematical.gsub(/(#{names})_\${(#{indice}+)}\$/, '\1<sub>{\2}</sub>') | |
mathematical = mathematical.gsub(/(#{names})\^\${(#{indice}+)}\$/, '\1<sup>{\2}</sup>') | |
mathematical = mathematical.gsub(/(#{names})_{(#{indice}+)}/, '\1<sub>\2</sub>') | |
mathematical = mathematical.gsub(/(#{names})\^{(#{indice}+)}/, '\1<sup>\2</sup>') | |
mathematical | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
= 始まり | |
静寂な朝。 | |
白基調のログハウス、高さ5メートル、風がよく通った部屋。 | |
青くて白い、春の空。 | |
//talkright[mu-smile]{ | |
お風呂上がったよ〜。 | |
//} | |
彼女が歩いてくる。 | |
歩きながら揺れる、リボンでくくったふわふわの髪を、目が追う。 | |
//talkleft[eta-arms]{ | |
……。 | |
//} | |
肩や首にかかる、なだらかな曲線からする、フローラルな香り。 | |
μと一緒に暮らし始めてから何年も経つっていうのに、いつまでも慣れはしない。 | |
ドキドキしちゃうから、少しクールぶって言葉を返す。 | |
//talkleft[eta-smile]{ | |
おかえり、μ。 | |
//} | |
//talkright[mu-wink]{ | |
ただいまη♪ | |
//} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment