루비 문자 변환기 바로가기

루비 문자는 글자 위에 첨자가 붙는 것으로서 아래와 같은 것들을 루비 문자라고 합니다. 모든 문자 및 언어에서 사용되는 것이지만 주로 일본어 등에서 볼 수 있습니다. (나무위키 루비 문자)

 

HTML으로 이 루비 문자를 입력할 수 있는데, 매번 태그를 입력하는 것이 귀찮기 때문에 변환기를 만들었습니다. 사용법은 루비 문자 변환기 사이트에 나와 있습니다.


<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>루비 문자 변환기</title>
<link rel="stylesheet" href="./bootstrap.min.css">
<style>
body {
width: 100%;
}
pre {
white-space: pre-wrap;
}
button[id^='copy-'] {
width: 100%;
}
#inst-title {
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<div class="row mt-2">
<div class="col">
<h3>루비 문자 변환기</h3>
</div>
</div>
<div class="row mt-2">
<div class="col">
<h6 id="inst-title" data-is-expanded="true">사용법 ▲</h6>
<div id="inst-area" class="rounded p-2 bg-light">
<p>텍스트 입력란에 중괄호 <code>{ }</code>와 막대기 기호<code> | </code>를 사용하여 아래와 같이 작성합니다.<br> <span class="text-primary">[변환]</span> 버튼을 누르면 결과가 아래에 뜨며, 특정 영역을 마우스로 선택한 뒤 <span class="text-primary">[선택 영역을 {|}로 치환]</span> 버튼을 누르면 해당 부분을
루비 문자 변환식으로 치환합니다.<br><span class="text-primary">[괄호]</span>는 루비 태그를 지원하지 않는 브라우저에서 표시할 때 사용하는 괄호를 지정합니다. 이 부분은 지정하지 않아도 무방합니다.</p>
<p>(1) <code>{루비 아래 텍스트|루비 위 텍스트}</code>
<br> (2) <code>{루비 아래 텍스트|루비 위 텍스트 1|루비 위 텍스트 2|…}</code> '루비 위 텍스트'의 갯수는 '루비 아래 텍스트'의 글자 수만큼 추가합니다. </p>
<p>(예1) <code>{가나다|ganada}</code> <ruby>
<rb>가</rb>
<rt>ga</rt>
<rb>나</rb>
<rt>na</rt>
<rb>다</rb>
<rt>da</rt>
</ruby>
<br> (예2) <code>{振り仮名|ふ||が|な}</code> <ruby>
<rb>振</rb>
<rt>ふ</rt>
<rb>り</rb>
<rt></rt>
<rb>仮</rb>
<rt>が</rt>
<rb>名</rb>
<rt>な</rt>
</ruby>
</p>
</div>
</div>
</div>
<div class="form-group">
<label>괄호</label>
<select id="parenthesis">
<option value="0">-없음-</option>
<option value="1">《》</option>
<option value="2">()</option>
<option value="3">〔〕</option>
<option value="4">[]</option>
</select>
<button id="btn-change" class="btn-primary">변환</button>
<button id="btn-replace-selection" class="btn-secondary">선택 영역을 {|}로 치환</button>
</div>
<div class="form-group ">
<textarea id="input-raw" class="form-control" rows="5" style="width: 100%;"></textarea>
</div>
<div id="result-area" class="row">
<div class="col-12">
<div class="row">
<div class="col-8">
<h6>HTML 소스</h6>
</div>
<div class="col">
<button id="copy-raw" class="btn-sm btn-link">&lt;&gt; 클립보드에 복사</button>
</div>
</div>
<pre id="raw-result" class="border border-secondary p-2 rounded bg-light"></pre>
<div class="row">
<div class="col-12">
<h6>미리보기</h6>
</div>
</div>
<div id="html-result" class="border border-secondary p-2 rounded"></div>
</div>
</div>
<div id="footer" class="row mt-2">
<div class="col-12">
&copy; 2019 <a href="http://yoonbumtae.com" target="_blank">BGSMM</a>
</div>
</div>
</div>
<script src="./jquery-3.4.1.min.js"></script>
<script src="./rangyinputs-jquery-src.js"></script>
<script src="./bootstrap.min.js"></script>
<script>
const example = `가나다 {確認|かくにん}하겠습니까? {確認|かく|にん}하겠습니까? {確認|かく|に|ん}하겠습니까? {確認}하겠습니까?`
const regex = /{(.+?)}/g
const DEBUG = false
$("#result-area").hide()
$(".alert").hide()
const btnChange = document.getElementById('btn-change')
btnChange.onclick = e => {
const rawText = document.getElementById('input-raw').value
const select = document.getElementById('parenthesis')
const out = changeToRuby(rawText, select.options[select.selectedIndex].value)
DEBUG && alert(select.options[select.selectedIndex].value)
document.getElementById('raw-result').innerHTML = out.replace(/</g, '&lt;').replace(/>/g, '&gt;')
document.getElementById('html-result').innerHTML = out
$("#result-area").show()
}
// 마우스로 텍스트를 선택한 곳을 특정 문구로 치환하는 기능
// rangyinputs-jquery-src.js (https://github.com/timdown/rangyinputs) 플러그인 사용
const btnReplaceSelection = document.getElementById('btn-replace-selection')
btnReplaceSelection.onclick = e => {
const inputRaw = $("#input-raw")
const selection = inputRaw.getSelection()
DEBUG && alert(selection.start)
DEBUG && alert(selection.length)
// 치환 후 이동할 커서 위치를 지정
const caretPos = selection.start + selection.length + 2
if (selection.length != 0) {
inputRaw.replaceSelectedText(`{${selection.text}|}`)
inputRaw.setSelection(caretPos)
}
}
$("#inst-title").on("click", e => {
$("#inst-area").toggle(200)
if ($(e.target).data("isExpanded")) {
$(e.target).text("사용법 ▼")
} else {
$(e.target).text("사용법 ▲")
}
$(e.target).data("isExpanded", !$(e.target).data("isExpanded"))
})
$("#copy-raw").on("click", e => {
copyToClipboard($("#raw-result").text())
})
function changeToRuby(rawText, opt_parentheseValue) {
const wrongMsgs = []
const rubiedText = rawText.replace(regex, function(match, group) {
DEBUG && console.log(match, group)
const parenthesis = {
left: "",
right: ""
}
switch (opt_parentheseValue) {
case "1":
parenthesis.left = "<rp>《</rp>"
parenthesis.right = "<rp>》</rp>"
break;
case "2":
parenthesis.left = "<rp>(</rp>"
parenthesis.right = "<rp>)</rp>"
break;
case "3":
parenthesis.left = "<rp>〔</rp>"
parenthesis.right = "<rp>〕</rp>"
break;
case "4":
parenthesis.left = "<rp>[</rp>"
parenthesis.right = "<rp>]</rp>"
break;
default:
}
let isError = false,
base = ""
const arr = group.split("|")
if (arr.length == 2) {
// 일반적인 경우 {밑|위}
base += `<rb>${arr[0]}</rb>`
base += `${parenthesis.left}<rt>${arr[1]}</rt>${parenthesis.right}`
} else if (arr.length > 2) {
// 개별 문자별로 루비 지정 {밑|위1|위2|…}
const charArr = arr[0].split('')
// 루비 밑의 문자수와 파라미터 수(맨 앞 제외)가 일치하는지 확인
if (charArr.length == arr.length – 1) {
for (let i = 0; i < charArr.length; i++) {
base += `<rb>${charArr[i]}</rb>`
base += `${parenthesis.left}<rt>${arr[i + 1]}</rt>${parenthesis.right}`
}
} else {
isError = true
wrongMsgs.push(`${match} : 루비 아래 문자의 수와 위 문자의 개수가 일치하지 않습니다.`)
}
} else {
// 입력 형식에 맞지 않는 경우
isError = true
wrongMsgs.push(`${match} : 괄호 안의 파라미터는 최소 2개 이상이어야 합니다.`)
}
const out = !isError ? `<ruby>${base}</ruby>` : match
DEBUG && console.log("final", out)
return out
})
if (wrongMsgs.length > 0) {
alert(wrongMsgs.join("\n"))
}
return rubiedText
}
// 클립보드 복사
function copyToClipboard(val) {
var t = document.createElement("textarea");
document.body.appendChild(t);
t.value = val;
t.select();
document.execCommand('copy');
document.body.removeChild(t);
alert("복사되었습니다.")
}
</script>
</body></html>

view raw

ruby.html

hosted with ❤ by GitHub

이 예제를 만들면서 rangyinputs 이라는 텍스트 선택 영역을 제어할 수 있는 편리한 제이쿼리 플러그인을 발견했는데 이에 대해서는 다음에 관련 글을 올리도록 하겠습니다.

 

결과 화면

 

오류가 발생하면 내용을 설명합니다.

 

문의 | 코멘트 또는 yoonbumtae@gmail.com


카테고리: WEB: Frontend


0개의 댓글

답글 남기기

Avatar placeholder

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다