seonbi (empty) → 0.1.0
raw patch · 40 files changed
+14611/−0 lines, 40 filesdep +QuickCheckdep +aesondep +attoparsecbuild-type:Customsetup-changed
Dependencies added: QuickCheck, aeson, attoparsec, base, bytestring, cases, cassava, containers, data-default, doctest, doctest-discover, file-embed, filepath, hlint, hspec, hspec-discover, html-charset, http-types, iconv, optparse-applicative, seonbi, text, text-trie, unicode-show, wai, warp
Files
- CHANGES.md +7/−0
- LICENSE +502/−0
- README.md +153/−0
- Setup.hs +76/−0
- app/seonbi-api.hs +234/−0
- app/seonbi.hs +393/−0
- data/ko-kr-stdict.tsv too large to diff
- seonbi.cabal +242/−0
- src/Text/Seonbi/Facade.hs +335/−0
- src/Text/Seonbi/Hangul.hs +88/−0
- src/Text/Seonbi/Hanja.hs +549/−0
- src/Text/Seonbi/Html.hs +21/−0
- src/Text/Seonbi/Html/Clipper.hs +111/−0
- src/Text/Seonbi/Html/Entity.hs +64/−0
- src/Text/Seonbi/Html/Preservation.hs +41/−0
- src/Text/Seonbi/Html/Printer.hs +74/−0
- src/Text/Seonbi/Html/Scanner.hs +177/−0
- src/Text/Seonbi/Html/Tag.hs +327/−0
- src/Text/Seonbi/Html/TagStack.hs +146/−0
- src/Text/Seonbi/Html/TextNormalizer.hs +81/−0
- src/Text/Seonbi/Html/Wrapper.hs +64/−0
- src/Text/Seonbi/PairedTransformer.hs +121/−0
- src/Text/Seonbi/Punctuation.hs +632/−0
- src/Text/Seonbi/Trie.hs +17/−0
- src/Text/Seonbi/Unihan/KHangul.hs +104/−0
- src/Text/Seonbi/Unihan/kHangul.json +8413/−0
- test/Spec.hs +1/−0
- test/Text/Seonbi/FacadeSpec.hs +41/−0
- test/Text/Seonbi/HangulSpec.hs +35/−0
- test/Text/Seonbi/HanjaSpec.hs +341/−0
- test/Text/Seonbi/Html/ClipperSpec.hs +186/−0
- test/Text/Seonbi/Html/PreservationSpec.hs +51/−0
- test/Text/Seonbi/Html/PrinterSpec.hs +40/−0
- test/Text/Seonbi/Html/ScannerSpec.hs +295/−0
- test/Text/Seonbi/Html/TextNormalizerSpec.hs +76/−0
- test/Text/Seonbi/Html/WrapperSpec.hs +61/−0
- test/Text/Seonbi/PunctuationSpec.hs +456/−0
- test/Text/Seonbi/Unihan/KHangulSpec.hs +43/−0
- test/doctest.hs +1/−0
- test/hlint.hs +12/−0
+ CHANGES.md view
@@ -0,0 +1,7 @@+Seonbi changelog+================++Version 0.1.0+-------------++Released on October 6, 2019.
+ LICENSE view
@@ -0,0 +1,502 @@+ GNU LESSER GENERAL PUBLIC LICENSE+ Version 2.1, February 1999++ Copyright (C) 1991, 1999 Free Software Foundation, Inc.+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++[This is the first released version of the Lesser GPL. It also counts+ as the successor of the GNU Library Public License, version 2, hence+ the version number 2.1.]++ Preamble++ The licenses for most software are designed to take away your+freedom to share and change it. By contrast, the GNU General Public+Licenses are intended to guarantee your freedom to share and change+free software--to make sure the software is free for all its users.++ This license, the Lesser General Public License, applies to some+specially designated software packages--typically libraries--of the+Free Software Foundation and other authors who decide to use it. You+can use it too, but we suggest you first think carefully about whether+this license or the ordinary General Public License is the better+strategy to use in any particular case, based on the explanations below.++ When we speak of free software, we are referring to freedom of use,+not price. Our General Public Licenses are designed to make sure that+you have the freedom to distribute copies of free software (and charge+for this service if you wish); that you receive source code or can get+it if you want it; that you can change the software and use pieces of+it in new free programs; and that you are informed that you can do+these things.++ To protect your rights, we need to make restrictions that forbid+distributors to deny you these rights or to ask you to surrender these+rights. These restrictions translate to certain responsibilities for+you if you distribute copies of the library or if you modify it.++ For example, if you distribute copies of the library, whether gratis+or for a fee, you must give the recipients all the rights that we gave+you. You must make sure that they, too, receive or can get the source+code. If you link other code with the library, you must provide+complete object files to the recipients, so that they can relink them+with the library after making changes to the library and recompiling+it. And you must show them these terms so they know their rights.++ We protect your rights with a two-step method: (1) we copyright the+library, and (2) we offer you this license, which gives you legal+permission to copy, distribute and/or modify the library.++ To protect each distributor, we want to make it very clear that+there is no warranty for the free library. Also, if the library is+modified by someone else and passed on, the recipients should know+that what they have is not the original version, so that the original+author's reputation will not be affected by problems that might be+introduced by others.++ Finally, software patents pose a constant threat to the existence of+any free program. We wish to make sure that a company cannot+effectively restrict the users of a free program by obtaining a+restrictive license from a patent holder. Therefore, we insist that+any patent license obtained for a version of the library must be+consistent with the full freedom of use specified in this license.++ Most GNU software, including some libraries, is covered by the+ordinary GNU General Public License. This license, the GNU Lesser+General Public License, applies to certain designated libraries, and+is quite different from the ordinary General Public License. We use+this license for certain libraries in order to permit linking those+libraries into non-free programs.++ When a program is linked with a library, whether statically or using+a shared library, the combination of the two is legally speaking a+combined work, a derivative of the original library. The ordinary+General Public License therefore permits such linking only if the+entire combination fits its criteria of freedom. The Lesser General+Public License permits more lax criteria for linking other code with+the library.++ We call this license the "Lesser" General Public License because it+does Less to protect the user's freedom than the ordinary General+Public License. It also provides other free software developers Less+of an advantage over competing non-free programs. These disadvantages+are the reason we use the ordinary General Public License for many+libraries. However, the Lesser license provides advantages in certain+special circumstances.++ For example, on rare occasions, there may be a special need to+encourage the widest possible use of a certain library, so that it becomes+a de-facto standard. To achieve this, non-free programs must be+allowed to use the library. A more frequent case is that a free+library does the same job as widely used non-free libraries. In this+case, there is little to gain by limiting the free library to free+software only, so we use the Lesser General Public License.++ In other cases, permission to use a particular library in non-free+programs enables a greater number of people to use a large body of+free software. For example, permission to use the GNU C Library in+non-free programs enables many more people to use the whole GNU+operating system, as well as its variant, the GNU/Linux operating+system.++ Although the Lesser General Public License is Less protective of the+users' freedom, it does ensure that the user of a program that is+linked with the Library has the freedom and the wherewithal to run+that program using a modified version of the Library.++ The precise terms and conditions for copying, distribution and+modification follow. Pay close attention to the difference between a+"work based on the library" and a "work that uses the library". The+former contains code derived from the library, whereas the latter must+be combined with the library in order to run.++ GNU LESSER GENERAL PUBLIC LICENSE+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION++ 0. This License Agreement applies to any software library or other+program which contains a notice placed by the copyright holder or+other authorized party saying it may be distributed under the terms of+this Lesser General Public License (also called "this License").+Each licensee is addressed as "you".++ A "library" means a collection of software functions and/or data+prepared so as to be conveniently linked with application programs+(which use some of those functions and data) to form executables.++ The "Library", below, refers to any such software library or work+which has been distributed under these terms. A "work based on the+Library" means either the Library or any derivative work under+copyright law: that is to say, a work containing the Library or a+portion of it, either verbatim or with modifications and/or translated+straightforwardly into another language. (Hereinafter, translation is+included without limitation in the term "modification".)++ "Source code" for a work means the preferred form of the work for+making modifications to it. For a library, complete source code means+all the source code for all modules it contains, plus any associated+interface definition files, plus the scripts used to control compilation+and installation of the library.++ Activities other than copying, distribution and modification are not+covered by this License; they are outside its scope. The act of+running a program using the Library is not restricted, and output from+such a program is covered only if its contents constitute a work based+on the Library (independent of the use of the Library in a tool for+writing it). Whether that is true depends on what the Library does+and what the program that uses the Library does.++ 1. You may copy and distribute verbatim copies of the Library's+complete source code as you receive it, in any medium, provided that+you conspicuously and appropriately publish on each copy an+appropriate copyright notice and disclaimer of warranty; keep intact+all the notices that refer to this License and to the absence of any+warranty; and distribute a copy of this License along with the+Library.++ You may charge a fee for the physical act of transferring a copy,+and you may at your option offer warranty protection in exchange for a+fee.++ 2. You may modify your copy or copies of the Library or any portion+of it, thus forming a work based on the Library, and copy and+distribute such modifications or work under the terms of Section 1+above, provided that you also meet all of these conditions:++ a) The modified work must itself be a software library.++ b) You must cause the files modified to carry prominent notices+ stating that you changed the files and the date of any change.++ c) You must cause the whole of the work to be licensed at no+ charge to all third parties under the terms of this License.++ d) If a facility in the modified Library refers to a function or a+ table of data to be supplied by an application program that uses+ the facility, other than as an argument passed when the facility+ is invoked, then you must make a good faith effort to ensure that,+ in the event an application does not supply such function or+ table, the facility still operates, and performs whatever part of+ its purpose remains meaningful.++ (For example, a function in a library to compute square roots has+ a purpose that is entirely well-defined independent of the+ application. Therefore, Subsection 2d requires that any+ application-supplied function or table used by this function must+ be optional: if the application does not supply it, the square+ root function must still compute square roots.)++These requirements apply to the modified work as a whole. If+identifiable sections of that work are not derived from the Library,+and can be reasonably considered independent and separate works in+themselves, then this License, and its terms, do not apply to those+sections when you distribute them as separate works. But when you+distribute the same sections as part of a whole which is a work based+on the Library, the distribution of the whole must be on the terms of+this License, whose permissions for other licensees extend to the+entire whole, and thus to each and every part regardless of who wrote+it.++Thus, it is not the intent of this section to claim rights or contest+your rights to work written entirely by you; rather, the intent is to+exercise the right to control the distribution of derivative or+collective works based on the Library.++In addition, mere aggregation of another work not based on the Library+with the Library (or with a work based on the Library) on a volume of+a storage or distribution medium does not bring the other work under+the scope of this License.++ 3. You may opt to apply the terms of the ordinary GNU General Public+License instead of this License to a given copy of the Library. To do+this, you must alter all the notices that refer to this License, so+that they refer to the ordinary GNU General Public License, version 2,+instead of to this License. (If a newer version than version 2 of the+ordinary GNU General Public License has appeared, then you can specify+that version instead if you wish.) Do not make any other change in+these notices.++ Once this change is made in a given copy, it is irreversible for+that copy, so the ordinary GNU General Public License applies to all+subsequent copies and derivative works made from that copy.++ This option is useful when you wish to copy part of the code of+the Library into a program that is not a library.++ 4. You may copy and distribute the Library (or a portion or+derivative of it, under Section 2) in object code or executable form+under the terms of Sections 1 and 2 above provided that you accompany+it with the complete corresponding machine-readable source code, which+must be distributed under the terms of Sections 1 and 2 above on a+medium customarily used for software interchange.++ If distribution of object code is made by offering access to copy+from a designated place, then offering equivalent access to copy the+source code from the same place satisfies the requirement to+distribute the source code, even though third parties are not+compelled to copy the source along with the object code.++ 5. A program that contains no derivative of any portion of the+Library, but is designed to work with the Library by being compiled or+linked with it, is called a "work that uses the Library". Such a+work, in isolation, is not a derivative work of the Library, and+therefore falls outside the scope of this License.++ However, linking a "work that uses the Library" with the Library+creates an executable that is a derivative of the Library (because it+contains portions of the Library), rather than a "work that uses the+library". The executable is therefore covered by this License.+Section 6 states terms for distribution of such executables.++ When a "work that uses the Library" uses material from a header file+that is part of the Library, the object code for the work may be a+derivative work of the Library even though the source code is not.+Whether this is true is especially significant if the work can be+linked without the Library, or if the work is itself a library. The+threshold for this to be true is not precisely defined by law.++ If such an object file uses only numerical parameters, data+structure layouts and accessors, and small macros and small inline+functions (ten lines or less in length), then the use of the object+file is unrestricted, regardless of whether it is legally a derivative+work. (Executables containing this object code plus portions of the+Library will still fall under Section 6.)++ Otherwise, if the work is a derivative of the Library, you may+distribute the object code for the work under the terms of Section 6.+Any executables containing that work also fall under Section 6,+whether or not they are linked directly with the Library itself.++ 6. As an exception to the Sections above, you may also combine or+link a "work that uses the Library" with the Library to produce a+work containing portions of the Library, and distribute that work+under terms of your choice, provided that the terms permit+modification of the work for the customer's own use and reverse+engineering for debugging such modifications.++ You must give prominent notice with each copy of the work that the+Library is used in it and that the Library and its use are covered by+this License. You must supply a copy of this License. If the work+during execution displays copyright notices, you must include the+copyright notice for the Library among them, as well as a reference+directing the user to the copy of this License. Also, you must do one+of these things:++ a) Accompany the work with the complete corresponding+ machine-readable source code for the Library including whatever+ changes were used in the work (which must be distributed under+ Sections 1 and 2 above); and, if the work is an executable linked+ with the Library, with the complete machine-readable "work that+ uses the Library", as object code and/or source code, so that the+ user can modify the Library and then relink to produce a modified+ executable containing the modified Library. (It is understood+ that the user who changes the contents of definitions files in the+ Library will not necessarily be able to recompile the application+ to use the modified definitions.)++ b) Use a suitable shared library mechanism for linking with the+ Library. A suitable mechanism is one that (1) uses at run time a+ copy of the library already present on the user's computer system,+ rather than copying library functions into the executable, and (2)+ will operate properly with a modified version of the library, if+ the user installs one, as long as the modified version is+ interface-compatible with the version that the work was made with.++ c) Accompany the work with a written offer, valid for at+ least three years, to give the same user the materials+ specified in Subsection 6a, above, for a charge no more+ than the cost of performing this distribution.++ d) If distribution of the work is made by offering access to copy+ from a designated place, offer equivalent access to copy the above+ specified materials from the same place.++ e) Verify that the user has already received a copy of these+ materials or that you have already sent this user a copy.++ For an executable, the required form of the "work that uses the+Library" must include any data and utility programs needed for+reproducing the executable from it. However, as a special exception,+the materials to be distributed need not include anything that is+normally distributed (in either source or binary form) with the major+components (compiler, kernel, and so on) of the operating system on+which the executable runs, unless that component itself accompanies+the executable.++ It may happen that this requirement contradicts the license+restrictions of other proprietary libraries that do not normally+accompany the operating system. Such a contradiction means you cannot+use both them and the Library together in an executable that you+distribute.++ 7. You may place library facilities that are a work based on the+Library side-by-side in a single library together with other library+facilities not covered by this License, and distribute such a combined+library, provided that the separate distribution of the work based on+the Library and of the other library facilities is otherwise+permitted, and provided that you do these two things:++ a) Accompany the combined library with a copy of the same work+ based on the Library, uncombined with any other library+ facilities. This must be distributed under the terms of the+ Sections above.++ b) Give prominent notice with the combined library of the fact+ that part of it is a work based on the Library, and explaining+ where to find the accompanying uncombined form of the same work.++ 8. You may not copy, modify, sublicense, link with, or distribute+the Library except as expressly provided under this License. Any+attempt otherwise to copy, modify, sublicense, link with, or+distribute the Library is void, and will automatically terminate your+rights under this License. However, parties who have received copies,+or rights, from you under this License will not have their licenses+terminated so long as such parties remain in full compliance.++ 9. You are not required to accept this License, since you have not+signed it. However, nothing else grants you permission to modify or+distribute the Library or its derivative works. These actions are+prohibited by law if you do not accept this License. Therefore, by+modifying or distributing the Library (or any work based on the+Library), you indicate your acceptance of this License to do so, and+all its terms and conditions for copying, distributing or modifying+the Library or works based on it.++ 10. Each time you redistribute the Library (or any work based on the+Library), the recipient automatically receives a license from the+original licensor to copy, distribute, link with or modify the Library+subject to these terms and conditions. You may not impose any further+restrictions on the recipients' exercise of the rights granted herein.+You are not responsible for enforcing compliance by third parties with+this License.++ 11. If, as a consequence of a court judgment or allegation of patent+infringement or for any other reason (not limited to patent issues),+conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License. If you cannot+distribute so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you+may not distribute the Library at all. For example, if a patent+license would not permit royalty-free redistribution of the Library by+all those who receive copies directly or indirectly through you, then+the only way you could satisfy both it and this License would be to+refrain entirely from distribution of the Library.++If any portion of this section is held invalid or unenforceable under any+particular circumstance, the balance of the section is intended to apply,+and the section as a whole is intended to apply in other circumstances.++It is not the purpose of this section to induce you to infringe any+patents or other property right claims or to contest validity of any+such claims; this section has the sole purpose of protecting the+integrity of the free software distribution system which is+implemented by public license practices. Many people have made+generous contributions to the wide range of software distributed+through that system in reliance on consistent application of that+system; it is up to the author/donor to decide if he or she is willing+to distribute software through any other system and a licensee cannot+impose that choice.++This section is intended to make thoroughly clear what is believed to+be a consequence of the rest of this License.++ 12. If the distribution and/or use of the Library is restricted in+certain countries either by patents or by copyrighted interfaces, the+original copyright holder who places the Library under this License may add+an explicit geographical distribution limitation excluding those countries,+so that distribution is permitted only in or among countries not thus+excluded. In such case, this License incorporates the limitation as if+written in the body of this License.++ 13. The Free Software Foundation may publish revised and/or new+versions of the Lesser General Public License from time to time.+Such new versions will be similar in spirit to the present version,+but may differ in detail to address new problems or concerns.++Each version is given a distinguishing version number. If the Library+specifies a version number of this License which applies to it and+"any later version", you have the option of following the terms and+conditions either of that version or of any later version published by+the Free Software Foundation. If the Library does not specify a+license version number, you may choose any version ever published by+the Free Software Foundation.++ 14. If you wish to incorporate parts of the Library into other free+programs whose distribution conditions are incompatible with these,+write to the author to ask for permission. For software which is+copyrighted by the Free Software Foundation, write to the Free+Software Foundation; we sometimes make exceptions for this. Our+decision will be guided by the two goals of preserving the free status+of all derivatives of our free software and of promoting the sharing+and reuse of software generally.++ NO WARRANTY++ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.++ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH+DAMAGES.++ END OF TERMS AND CONDITIONS++ How to Apply These Terms to Your New Libraries++ If you develop a new library, and you want it to be of the greatest+possible use to the public, we recommend making it free software that+everyone can redistribute and change. You can do so by permitting+redistribution under these terms (or, alternatively, under the terms of the+ordinary General Public License).++ To apply these terms, attach the following notices to the library. It is+safest to attach them to the start of each source file to most effectively+convey the exclusion of warranty; and each file should have at least the+"copyright" line and a pointer to where the full notice is found.++ <one line to give the library's name and a brief idea of what it does.>+ Copyright (C) <year> <name of author>++ This library is free software; you can redistribute it and/or+ modify it under the terms of the GNU Lesser General Public+ License as published by the Free Software Foundation; either+ version 2.1 of the License, or (at your option) any later version.++ This library is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU+ Lesser General Public License for more details.++ You should have received a copy of the GNU Lesser General Public+ License along with this library; if not, write to the Free Software+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA++Also add information on how to contact you by electronic and paper mail.++You should also get your employer (if you work as a programmer) or your+school, if any, to sign a "copyright disclaimer" for the library, if+necessary. Here is a sample; alter the names:++ Yoyodyne, Inc., hereby disclaims all copyright interest in the+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.++ <signature of Ty Coon>, 1 April 1990+ Ty Coon, President of Vice++That's all there is to it!
+ README.md view
@@ -0,0 +1,153 @@+Seonbi: SmartyPants for Korean language+=======================================++[![][releases-badge]][releases] [![][hackage-badge]][hackage] [![][dockerhub-badge]][dockerhub] [![][ci-status-badge]][ci]++Seonbi (선비) is is an HTML preprocessor that makes typographic adjustments+to an HTML so that the result uses accurate punctuations according to+the modern Korean orthography.+(It's similar to what [SmartyPants] does for a text written in English.)++It also transforms a `ko-Kore` text (國漢文混用; [Korean mixed script]) into+a `ko-Hang` text (한글전용; Hangul-only script).++Seonbi provides a Haskell library, a CLI, and an HTTP API; any of them can+perform the following transformations:++ - All hanja words (e.g., `漢字`) into corresponding hangul-only words+ (e.g., `한자`)+ - Straight quotes and apostrophes (`"` & `'`) into curly quotes HTML+ entities (`“`, `”`, `‘`, & `’`)+ - Three consecutive periods (`...`) into an ellipsis entity (`…`)+ - Pairs of less-than and greater-than inequality symbols (`<` & `>`) into+ pairs of proper angle quotes (`〈` & `〉`)+ - Pairs of two consecutive inequality symbols (`<<` & `>>`) into+ pairs of proper double angle quotes (`《` & `》`)+ - A hyphen (`-`) or hangul vowel *eu* (`ㅡ`) surrounded by spaces, or+ two/three consecutive hyphens (`--` or `---`) into a proper em dash (`—`)+ - A less-than inequality symbol followed by a hyphen or an equality+ symbol (`<-`, `<=`) into arrows to the left (`←`, `⇐`)+ - A hyphen or an equality symbol followed by a greater-than inequality+ symbol (`->`, `=>`) into arrows to the right (`→`, `⇒`)+ - A hyphen or an equality symbol wrapped by inequality symbols (`<->`, `<=>`)+ into bi-directional arrows (`↔`, `⇔`)++Since its transformations work in HTML-level, it also plays well with web+markup languages like CommonMark, Markdown, and Textile. In a similar way to+SmartyPants, it either does not modify characters within several sensitive+HTML elements like `<pre>`/`<code>`/`<script>`/`<kbd>`.++[releases]: https://github.com/dahlia/seonbi/releases+[releases-badge]: https://img.shields.io/github/v/release/dahlia/seonbi+[hackage]: https://hackage.haskell.org/package/seonbi+[hackage-badge]: https://img.shields.io/hackage/v/seonbi+[dockerhub]: https://hub.docker.com/r/dahlia/seonbi+[dockerhub-badge]: https://img.shields.io/microbadger/image-size/dahlia/seonbi+[ci]: https://github.com/dahlia/seonbi/actions+[ci-status-badge]: https://github.com/dahlia/seonbi/workflows/build/badge.svg+[SmartyPants]: https://daringfireball.net/projects/smartypants/+[Korean mixed script]: https://en.wikipedia.org/wiki/Korean_mixed_script+++Installation+------------++Seonbi provides the official executable binaries for Linux (x86_64), macOS,+and Windows (64-bit). You can find download them from the [releases] page.++It is also distributed as a [Docker image][dockerhub]:++ $ echo '訓民正音' | docker run -i dahlia/seonbi:latest seonbi+ 훈민정음++If you want to use it as a Haskell library install the [seonbi][hackage] package+using Stack or Cabal.+++CLI+---++The `seonbi` command basically takes the input HTML as standard input, and+then transformes it into the output HTML as standard output:++ seonbi < input.html > output.html++You could pass a filename as an argument instead (and it is `-` by default):++ seonbi input.html > output.html++There is `-o`/`--output` option as well:++ seonbi -o output.html input.html++Although it automatically detects text encoding of the input file,+you could explicitly specify `-e`/`--encoding`:++ seobni -e euc-kr -o output.html input.html++Although there are several style options, e.g., `-q`/`--quote`, `-c`/`--cite`,+`-r`/`--render-hanja`, in most cases, giving `-p`/`--preset` is enough:++ echo '平壤 冷麵' | seonbi -p ko-kr # 평양 냉면+ echo '平壤 冷麵' | seonbi -p ko-kp # 평양 랭면++Read `-h`/`--help` for details:++ seonbi --help+++HTTP API+--------++The `seonbi-api` command starts an HTTP server that takes `POST` requests+with an HTML source with transformation options, and responds with+a transformed result HTML. You can decide a hostname and a port number+with `-H`/`--host` and `-p`/`--port` options:++ seonbi-api -H 0.0.0.0 -p 3800++The following is an example request:++ POST / HTTP/1.1+ Content-Type: application/json+ Host: localhost:3800++ {+ "preset": "ko-kr",+ "sourceHtml": "<p>하늘과 바람과 별과 詩</p>"+ }++The HTTP API server would respond like this:++ HTTP/1.1 200 OK+ Content-Type: application/json+ Server: Seonbi/0.1.0++ {+ "success": true,+ "resultHtml": "<p>하늘과 바람과 별과 시</p>"+ }++If a web app needs to use the HTTP API server, [CORS] should be configured+through `--allow-origin`/`-o` option:++ seonbi-api -o https://example.com++[CORS]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS+++License+-------++Distributed under LGPL 2.1 or later.+++Etymology+---------++*[Seonbi]* (선비) means a classical scholar during Joseon periods (14c–19c).+Today there's a meme that calls a person who feels morally superior or has+elitism *seonbi* in the Korean internet. So *seonbi* and *smarty pants* have+some things in common.++[Seonbi]: https://en.wikipedia.org/wiki/Seonbi
+ Setup.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE OverloadedStrings #-}+import Control.Monad+import Prelude hiding (concat)+import System.IO (Handle, IOMode (..), hClose, hSetEncoding, utf8, withFile)++import Codec.Archive.Zip+import Data.ByteString.Lazy (ByteString, hPut)+import Data.Text+import Data.Text.IO (hGetLine, hPutStrLn)+import Distribution.Simple+import Network.HTTP.Client+import System.Directory+import System.FilePath+import System.IO.Temp++unihanUrl :: String+unihanUrl = "http://ftp.unicode.org/Public/11.0.0/ucd/Unihan.zip"++kHangulPath :: FilePath+kHangulPath = "src" </> "Text" </> "Seonbi" </> "kHangul.txt"++main :: IO ()+main = do+ exist <- doesFileExist kHangulPath+ unless exist $ do+ data' <- downloadUnihan+ extractUnihanReadings data' $ \ txtPath -> do+ values <- withFile txtPath ReadMode (extractProp "kHangul")+ withFile kHangulPath WriteMode $ \ handle -> do+ hSetEncoding handle utf8+ forM_ values $ \ (char, value) ->+ hPutStrLn handle $ concat [char, "\t", value]+ defaultMain++extractProp :: Text -> Handle -> IO [(Text, Text)]+extractProp property handle = do+ hSetEncoding handle utf8+ line <- hGetLine handle+ case line of+ "" ->+ return []+ line' ->+ case breakOn "\t" line' of+ (_, "") ->+ extractProp property handle+ (char, rest)+ | "U+" `isPrefixOf` char && "\t" `isPrefixOf` rest ->+ case breakOn "\t" $ Data.Text.tail rest of+ (_, "") ->+ extractProp property handle+ (prop, value) | prop == property ->+ ((char, value) :) <$> extractProp property handle+ _ ->+ extractProp property handle+ _ ->+ extractProp property handle+ ++extractUnihanReadings :: ByteString -> (FilePath -> IO a) -> IO a+extractUnihanReadings data' callback =+ withSystemTempFile "Unihan.zip" $ \ zipPath handle -> do+ hPut handle data'+ hClose handle+ let entryName = "Unihan_Readings.txt"+ withSystemTempFile entryName $ \ txtPath handle' -> do+ hClose handle'+ sel <- mkEntrySelector entryName+ withArchive zipPath (saveEntry sel txtPath)+ callback txtPath++downloadUnihan :: IO ByteString+downloadUnihan = do+ mgr <- newManager defaultManagerSettings+ req <- parseRequest unihanUrl+ res <- httpLbs req mgr+ return $ responseBody res
+ app/seonbi-api.hs view
@@ -0,0 +1,234 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+module Main (main) where++import Control.Concurrent (threadDelay)+import Control.Monad+import Data.String+import Data.Version+import GHC.Exts (IsList (..))+import System.IO++import Data.Aeson+import qualified Data.Aeson.Types+import qualified Data.ByteString as B+import qualified Data.Map.Strict as M+import Data.Text+import Data.Text.Encoding+import Network.Wai+import Network.HTTP.Types+import Network.Wai.Handler.Warp+import Options.Applicative++import qualified Paths_seonbi as Meta+import Text.Seonbi.Facade+import Text.Seonbi.Trie as Trie++data Input = Input+ { sourceHtml :: Text+ , configuration :: Configuration IO ()+ } deriving (Show)++instance FromJSON Input where+ parseJSON = withObject "Input" $ \ v -> do+ sourceHtml' <- v .: "sourceHtml"+ preset <- v .:? "preset"+ config <- case preset of+ Just locale ->+ let presets' = presets :: M.Map Text (Configuration IO ())+ m = M.lookup (replace "_" "-" $ toLower locale) presets'+ in+ case m of+ Just p -> return p+ Nothing -> fail $ unpack $ Data.Text.concat+ [ "No such preset: "+ , locale+ , "; available presets: "+ , intercalate ", " (M.keys presets')+ ]+ Nothing -> do+ xhtml' <- v .:? "xhtml" .!= False+ quote' <- v .:? "quote"+ cite' <- v .:? "cite"+ arrow' <- v .:? "arrow"+ ellipsis' <- v .:? "ellipsis" .!= False+ emDash' <- v .:? "emDash" .!= False+ hanja' <- v .:? "hanja" .!= Nothing+ return Configuration+ { debugLogger = Nothing+ , xhtml = xhtml'+ , quote = quote'+ , cite = cite'+ , arrow = arrow'+ , ellipsis = ellipsis'+ , emDash = emDash'+ , hanja = hanja'+ }+ return $ Input sourceHtml' config++instance FromJSON QuoteOption+instance FromJSON CiteOption+instance FromJSON ArrowOption+instance FromJSON HanjaRenderingOption++instance FromJSON HanjaOption where+ parseJSON = withObject "HanjaOption" $ \ v -> HanjaOption+ <$> v .: "rendering"+ <*> v .: "reading"++instance FromJSON HanjaReadingOption where+ parseJSON = withObject "HanjaReadingOption" $ \ v -> do+ initialSoundLaw <- v .:? "initialSoundLaw" .!= False+ wordMap <- v .:? "dictionary" .!= []+ let wordPairs = GHC.Exts.toList (wordMap :: Object)+ dictionary <- forM wordPairs $ \ (key, val) -> do+ val' <- withText "Hangul string" return val+ return (key, val')+ let customDict = Trie.fromList dictionary+ dictIds <- v .:? "useDictionaries" .!= []+ useDictionaries <- forM (dictIds :: Array) $+ withText "Dictionary ID string" getDictById+ let dict = Prelude.foldl unionL customDict useDictionaries+ return $ HanjaReadingOption initialSoundLaw dict+ where+ getDictById :: Text -> Data.Aeson.Types.Parser HanjaDictionary+ getDictById "kr-stdict" = return southKoreanDictionaryUnsafe+ getDictById dictId = fail ("No such dictionary ID: " ++ unpack dictId)+ southKoreanDictionaryUnsafe :: HanjaDictionary+ southKoreanDictionaryUnsafe = case hanja ko_KR' of+ Just HanjaOption { reading = HanjaReadingOption { dictionary } } ->+ dictionary+ Nothing ->+ Trie.empty+ ko_KR' :: Configuration IO ()+ ko_KR' = ko_KR+++app :: AppOptions -> Application+app AppOptions { allowOrigin, debugDelayMs } request respond =+ case requestMethod request of+ "POST" -> do+ inputJson <- lazyRequestBody request+ threadDelay (debugDelayMs * 1000)+ case eitherDecode' inputJson of+ Right (Input source config) -> do+ result <- transformHtmlText config source+ respond' status200 $ object+ [ "success" .= Bool True+ , "resultHtml" .= String result+ ]+ Left msg -> respond' status400 $ object+ [ "success" .= Bool False+ , "message" .= String (pack msg)+ ]+ "OPTIONS" ->+ respond' status200 Null+ method -> respond' status405 $ object+ [ "success" .= Bool False+ , "message" .= String ("Unsupported method: " <> decodeUtf8 method)+ ]+ where+ respond' :: ToJSON a => Status -> a -> IO ResponseReceived+ respond' status value' =+ respond $ responseLBS status headers (encode value')+ headers :: [Header]+ headers = headerAdder+ [ ("Content-Type", "application/json")+ , ("Access-Control-Allow-Headers", "content-type")+ ]+ headerAdder :: [Header] -> [Header]+ headerAdder = case allowOrigin of+ Just origin -> (("Access-Control-Allow-Origin", origin) :)+ Nothing -> id++string :: IsString a => ReadM a+string = maybeReader (Just . fromString)++showHostPreference :: HostPreference -> String+showHostPreference h = case show h of+ "HostAny" -> "[::]"+ "HostIPv4" -> "0.0.0.0"+ "HostIPv4Only" -> "0.0.0.0"+ "HostIPv6" -> "[::]"+ "HostIPv6Only" -> "[::]"+ 'H' : 'o' : 's' : 't' : ' ' : '"' : a ->+ Prelude.take (Prelude.length a - 1) a+ _ -> "?"++data CliOptions = CliOptions+ { serverSettings :: Settings+ , appOptions :: AppOptions+ }++data AppOptions = AppOptions+ { allowOrigin :: Maybe B.ByteString+ , debugDelayMs :: Int+ } deriving (Show, Eq)++parser :: Parser CliOptions+parser = CliOptions+ <$> ( setHost+ <$> option string+ ( long "host"+ <> short 'H'+ <> metavar "HOST"+ <> value "*"+ <> help "Host address to listen (default: [::/0])"+ )+ <*> ((`setPort` defaultSettings)+ <$> option auto+ ( long "port"+ <> short 'p'+ <> metavar "PORT"+ <> value 3800+ <> showDefault+ <> help "Port number to listen"+ )+ )+ )+ <*> ( AppOptions+ <$> (+ ( Just <$> strOption+ ( long "allow-origin"+ <> short 'o'+ <> metavar "ORIGIN"+ <> help "Allow cross-origin (i.e., CORS)"+ )+ )+ <|> pure Nothing+ )+ <*> option auto+ ( long "debug-delay"+ <> metavar "MS"+ <> value 0+ <> showDefault+ <> help "Delay time for client development"+ )+ )+ <**> helper++parserInfo :: ParserInfo CliOptions+parserInfo = info parser+ ( fullDesc+ <> progDesc "Seonbi HTTP API server"+ )++serverName :: B.ByteString+serverName =+ "Seonbi/" `B.append` encodeUtf8 (pack $ showVersion Meta.version)++main :: IO ()+main = do+ CliOptions+ { serverSettings = settings+ , appOptions+ } <- execParser parserInfo+ let serverSettings' = setServerName serverName settings+ let netloc = showHostPreference (getHost serverSettings') ++ ":" +++ show (getPort serverSettings')+ let url = "http://" ++ netloc ++ "/"+ hPutStrLn stderr url+ runSettings serverSettings' $ app appOptions
+ app/seonbi.hs view
@@ -0,0 +1,393 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Main (main) where++#ifndef ICONV+import Control.Exception+#endif+import Control.Monad+import Data.Char+import Data.List (intercalate)+import Data.Maybe+import Data.Proxy+import Data.Version+import Prelude hiding (getContents, putStr, readFile, writeFile)+import System.Exit+import System.IO (hPutStrLn, stderr)+import System.IO.Error++import Cases+#ifdef ICONV+import Codec.Text.IConv+#endif+import Data.ByteString.Lazy+import Data.Map.Strict+import qualified Data.Text as T+import Data.Text.Lazy+import Data.Text.Lazy.Encoding+import Options.Applicative+import Text.Html.Encoding.Detection (detect)++import qualified Paths_seonbi as Meta+import Text.Seonbi.Facade+import Text.Seonbi.Trie as Trie+import Text.Seonbi.Html.Entity++#ifndef ICONV+type EncodingName = String+#endif++toUnicode :: EncodingName -> ByteString -> Text+toUnicode encodingName =+ case normalizeEncodingName encodingName of+ "utf8" -> decodeUtf8+ "utf16le" -> decodeUtf16LE+ "utf16be" -> decodeUtf16BE+ "utf32le" -> decodeUtf32LE+ "utf32be" -> decodeUtf32BE+ _ ->+#ifdef ICONV+ decodeUtf8 . convert encodingName "UTF-8"+#else+ throw $ userError $+ "Only UTF-{8,16,32} encodings are supported, " +++ "since it is not built with iconv."+#endif++fromUnicode :: EncodingName -> Text -> ByteString+fromUnicode encodingName =+ case normalizeEncodingName encodingName of+ "utf8" -> encodeUtf8+ "utf16le" -> encodeUtf16LE+ "utf16be" -> encodeUtf16BE+ "utf32le" -> encodeUtf32LE+ "utf32be" -> encodeUtf32BE+ _ ->+#ifdef ICONV+ convert "UTF-8" encodingName . encodeUtf8+#else+ throw $ userError $+ "Only UTF-{8,16,32} encodings are supported, " +++ "since it is not built with iconv."+#endif++-- | Normalize the encoding name.+--+-- >>> normalizeEncodingName "UTF-8"+-- "utf8"+-- >>> normalizeEncodingName "UTF-16LE"+-- "utf16le"+-- >>> normalizeEncodingName "EUC-KR"+-- "euckr"+normalizeEncodingName :: EncodingName -> EncodingName+normalizeEncodingName =+ Prelude.filter (\ c -> isAscii c && isAlphaNum c) . fmap Data.Char.toLower++data Seonbi = Seonbi+ { output :: FilePath+ , encoding :: String+ , config :: Configuration IO ()+ , dictionaries :: [FilePath]+ , noKrStdict :: Bool+ , debug :: Bool+ , version :: Bool+ , input :: FilePath+ } deriving (Show)++presets' :: Map String (Configuration IO ())+presets' = presets++preset :: ReadM (Configuration IO ())+preset = eitherReader $ \ arg ->+ case Data.Map.Strict.lookup (normalize <$> arg) presets' of+ Just c -> Right c+ _ -> Left $ "no such preset: \"" ++ arg ++ "\""+ where+ normalize :: Char -> Char+ normalize = Data.Char.toLower . hyphenize+ hyphenize :: Char -> Char+ hyphenize '_' = '-'+ hyphenize c = c++hanjaReading :: ReadM (T.Text, T.Text)+hanjaReading = eitherReader $ \ arg ->+ case T.breakOn ":" $ T.pack arg of+ (_, "") -> Left $ "colon is missing: \"" ++ arg ++ "\""+ ("", _) -> Left $ "hanja writing is missing: \"" ++ arg ++ "\""+ (_, ":") -> Left $ "phonetic reading is missing: \"" ++ arg ++ "\""+ (writing, reading) -> Right (writing, T.drop 1 reading)++-- | Similar to 'auto', except it uses @spinal-case@ instead of @PascalCase@.+enum :: Read a => ReadM a+enum = eitherReader $ \ arg -> case reads (pascalize arg) of+ [(r, "")] -> return r+ _ -> Left $ "cannot parse value `" ++ arg ++ "'"+ where+ pascalize :: String -> String+ pascalize = T.unpack . process title camel . T.pack++enumKeyword' :: (Enum a, Show a) => a -> T.Text+enumKeyword' = spinalize . T.pack . show++enumKeyword :: (Enum a, Show a) => a -> String+enumKeyword = T.unpack . enumKeyword'++enumKeywords :: forall a . (Enum a, Show a) => Proxy a -> String+enumKeywords _ = T.unpack $ T.intercalate ", " $+ fmap enumKeyword' [(toEnum 0 :: a) ..]++parser :: Parser Seonbi+parser = Seonbi+ <$> strOption+ ( long "output"+ <> short 'o'+ <> metavar "FILE"+ <> value "-"+ <> help ("Output file path. A hyphen (-) means standard output. " +++ "To specify an actual file named \"-\", prepend its " +++ "relative path, e.g., \"./-\" [default: -]")+ )+ <*> strOption+ ( long "encoding"+ <> short 'e'+ <> metavar "ENCODING"+ <> value ""+ <> help "Character encoding (e.g., UTF-8, EUC-KR)"+ )+ <*> ( option preset+ ( long "preset"+ <> short 'p'+ <> help ("Use a preset instead of below style settings (this " +++ "resjects any other style options below). " +++ "Available presets: " +++ Data.List.intercalate ", " (Data.Map.Strict.keys presets'))+ )+ <|> ( Configuration Nothing+ <$> switch+ ( long "xhtml"+ <> short 'x'+ <> help "XHTML mode"+ )+ <*> ( flag' Nothing+ ( long "no-quote"+ <> short 'Q'+ <> help ("Do not transform any quotes at all. " +++ "This rejects -q/--quote option")+ )+ <|> option (fmap Just enum)+ ( long "quote"+ <> short 'q'+ <> metavar "QUOTE_STYLE"+ <> value (Just CurvedQuotes)+ <> help ("Quoting style. Available styles: " +++ enumKeywords (Proxy :: Proxy QuoteOption) +++ " [default: " ++ enumKeyword CurvedQuotes ++ "]")+ )+ )+ <*> option (fmap Just enum)+ ( long "cite"+ <> short 'c'+ <> metavar "CITE_STYLE"+ <> value Nothing+ <> help ("Transform citating quotes. Available styles: " +++ enumKeywords (Proxy :: Proxy CiteOption))+ )+ <*> ( flag' Nothing+ ( long "no-arrow"+ <> short 'A'+ <> help ("Do not transform any arrows at all. " +++ "This rejects -b/--bidir-arrow and " +++ "-d/--double-arrow options")+ )+ <|> ( fmap Just . ArrowOption+ <$> switch+ ( long "bidir-arrow"+ <> short 'b'+ <> help "Transform bi-directional arrows as well"+ )+ <*> switch+ ( long "double-arrow"+ <> short 'd'+ <> help "Transform double arrows as well"+ )+ )+ )+ <*> flag True False+ ( long "no-ellipsis"+ <> short 'E'+ <> help "Do not transform triple periods into a proper ellipsis"+ )+ <*> flag True False+ ( long "no-em-dash"+ <> short 'D'+ <> help "Do not transform folk em dashes into proper em dashes"+ )+ <*> ( flag' Nothing+ ( long "maintain-hanja"+ <> short 'H'+ <> help ("Leave Sino-Korean words as are. This rejects " +++ "-r/--render-hanja and " +++ "-I/--no-initial-sound-law options")+ )+ <|> ( fmap Just . HanjaOption+ <$> option enum+ ( long "render-hanja"+ <> short 'r'+ <> metavar "RENDERING_STYLE"+ <> value DisambiguatingHanjaInParentheses+ <> help ("How to render Sino-Korean words. " +++ "Available styles: " +++ enumKeywords+ (Proxy :: Proxy HanjaRenderingOption) +++ " [default: " +++ enumKeyword DisambiguatingHanjaInParentheses +++ "]")+ )+ <*> ( HanjaReadingOption+ <$> flag True False+ ( long "no-initial-sound-law"+ <> short 'I'+ <> help ("Do not apply Initial Sound Law " +++ "(頭音法則) Sino-Korean words. " +++ "This implies -S/--no-kr-stdict")+ )+ <*> ( Trie.fromList+ <$> many+ ( option hanjaReading+ ( long "read-hanja"+ <> short 'R'+ <> metavar "HANJA:HANGUL"+ <> help ("Add a custum reading of " +++ "Sino-Korean word. This " +++ "option can be multiple, " +++ "e.g., \"-R 孫文:쑨원 " +++ "-R 毛澤東:마오쩌둥\". " +++ "Prior to -D/--dict options")+ )+ )+ )+ )+ )+ )+ )+ )+ <*> many+ ( strOption+ ( long "dict"+ <> short 'D'+ <> metavar "FILE"+ <> help ("Give a custom dictionary to phonetize Sino-Korean " +++ "words. A dictionry file should be TSV (tab-separated " +++ "values) format of two columns; the first column is " +++ "hanja and the second column is hangul. " +++ "This option can be multiple.")+ )+ )+ <*> switch+ ( long "no-kr-stdict"+ <> short 'S'+ <> help ("Do not use Standard Korean Language Dictionary " +++ "(標準國語大辭典) by South Korean NIKL (國立國語院)")+ )+ <*> switch+ ( long "debug"+ <> hidden+ <> help "Debug mode"+ )+ <*> switch+ ( long "version"+ <> short 'v'+ <> hidden+ <> help "Show version"+ )+ <**> helper+ <*> argument str+ ( metavar "FILE"+ <> value "-"+ <> help ("Input HTML file. A hyphen (-) means standard input. " +++ "To specify an actual file named \"-\", prepend its " +++ "relative path, e.g., \"./-\" [default: -]")+ )++parserInfo :: ParserInfo Seonbi+parserInfo = info parser+ ( fullDesc+ <> progDesc "Korean typographic adjustment processor"+ )++showHtml :: HtmlEntity -> T.Text+showHtml HtmlStartTag { tag, rawAttributes } =+ T.concat ["<", T.pack (show tag), " ", rawAttributes, ">"]+showHtml HtmlEndTag { tag } =+ T.concat ["</", T.pack (show tag), ">"]+showHtml HtmlText { rawText } =+ T.concat ["!text ", rawText]+showHtml HtmlCdata { text } =+ T.concat ["!cdata ", text]+showHtml HtmlComment { comment } =+ T.concat ["<!-- ", comment, " -->"]++main :: IO ()+main = do+ options@Seonbi+ { encoding+ , config+ , dictionaries+ , noKrStdict+ , debug+ , version+ , input+ , output+ } <- execParser parserInfo+ let debugLogger' = if debug then Just logger else Nothing+ config' <- case hanja config of+ Nothing ->+ return config { debugLogger = debugLogger' }+ Just hanja'@HanjaOption+ { reading = HanjaReadingOption initialSoundLaw dict } -> do+ dicts <- forM dictionaries readDictionaryFile+ let customDict = Prelude.foldl unionL dict dicts+ dict' <- if not initialSoundLaw || noKrStdict+ then return customDict+ else do+ krStDict <- catchIOError southKoreanDictionary $+ const (return [])+ return $ unionL customDict krStDict+ let reading' = (reading hanja') { dictionary = dict' }+ return config+ { debugLogger = debugLogger'+ , hanja = Just hanja' { reading = reading' }+ }+ when version $ do+ Prelude.putStrLn $ showVersion Meta.version+ exitSuccess+ let whenDebug = when debug+ let debugPrint = whenDebug . hPutStrLn stderr+ debugPrint ("options: " ++ show options)+ contents <- if input == "-"+ then getContents+ else catchIOError (readFile input) $ \ e -> do+ hPutStrLn stderr $ ioeGetErrorString e +++ case ioeGetFileName e of+ Just msg -> ": " ++ msg+ Nothing -> ""+ exitFailure+ let encodingName = case encoding of+ "" -> fromMaybe "UTF-8" $ detect contents+ enc -> enc+ debugPrint ("encoding: " ++ encodingName)+ result <- catchIOError+ (transformHtmlLazyText config' $ toUnicode encodingName contents)+ (\ e -> hPutStrLn stderr (ioeGetErrorString e) >> exitFailure)+ let resultBytes = fromUnicode encodingName result+ if output == "-"+ then+ putStr resultBytes+ else+ writeFile output resultBytes+ where+ logger :: HtmlEntity -> IO ()+ logger = hPutStrLn stderr . T.unpack . showHtml
+ data/ko-kr-stdict.tsv view
file too large to diff
+ seonbi.cabal view
@@ -0,0 +1,242 @@+cabal-version: 1.24++-- This file has been generated from package.yaml by hpack version 0.31.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: d4a46f2e66dbb5471c1056a03c8d90108abbc383e058d391e679715309b07a2c++name: seonbi+version: 0.1.0+synopsis: SmartyPants for Korean language+description: Please see the README.md on GitHub at <https://github.com/dahlia/seonbi>.+category: Text+homepage: https://github.com/dahlia/seonbi+bug-reports: https://github.com/dahlia/seonbi/issues+author: Hong Minhee <hong.minhee@gmail.com>+maintainer: Hong Minhee <hong.minhee@gmail.com>+copyright: © 2018–2019 Hong Minhee+license: LGPL-2.1+license-file: LICENSE+build-type: Custom+extra-source-files:+ src/Text/Seonbi/Unihan/kHangul.json+ CHANGES.md+ README.md+data-files:+ ko-kr-stdict.tsv+data-dir: data++source-repository head+ type: git+ location: git://github.com/dahlia/seonbi.git++custom-setup+ setup-depends:+ Cabal+ , base+ , bytestring+ , directory >=1 && <2+ , filepath+ , http-client >=0.5 && <0.7+ , temporary >=1.2 && <1.4+ , text+ , zip >=1.1 && <1.3++flag iconv+ description: Use iconv+ manual: True+ default: False++flag static+ description: Static link+ manual: True+ default: False++library+ exposed-modules:+ Text.Seonbi.Facade+ Text.Seonbi.Hangul+ Text.Seonbi.Hanja+ Text.Seonbi.Html+ Text.Seonbi.Html.Clipper+ Text.Seonbi.Html.Entity+ Text.Seonbi.Html.Preservation+ Text.Seonbi.Html.Printer+ Text.Seonbi.Html.Scanner+ Text.Seonbi.Html.Tag+ Text.Seonbi.Html.TagStack+ Text.Seonbi.Html.TextNormalizer+ Text.Seonbi.Html.Wrapper+ Text.Seonbi.PairedTransformer+ Text.Seonbi.Punctuation+ Text.Seonbi.Trie+ Text.Seonbi.Unihan.KHangul+ other-modules:+ Paths_seonbi+ hs-source-dirs:+ src+ build-depends:+ aeson >=1.3.1 && <1.5+ , attoparsec >=0.12 && <1+ , base >=4.7 && <5+ , bytestring+ , cassava >=0.5 && <0.6+ , containers+ , data-default >=0.2 && <1+ , file-embed >=0.0.10 && <0.0.12+ , filepath >=1 && <2+ , text+ , text-trie >=0.2.5 && <0.3+ if os(darwin)+ ghc-options: -Wall -fprint-explicit-kinds -optP-Wno-nonportable-include-path+ else+ ghc-options: -Wall -fprint-explicit-kinds+ default-language: Haskell2010++executable seonbi+ main-is: seonbi.hs+ other-modules:+ Paths_seonbi+ hs-source-dirs:+ app+ build-depends:+ aeson >=1.3.1 && <1.5+ , base >=4.7 && <5+ , bytestring+ , containers+ , text+ if os(darwin)+ ghc-options: -Wall -fprint-explicit-kinds -optP-Wno-nonportable-include-path+ else+ ghc-options: -Wall -fprint-explicit-kinds+ if flag(iconv)+ cpp-options: -DICONV+ build-depends:+ cases ==0.1.3.2+ , html-charset >=0.1 && <0.2+ , iconv >=0.4 && <0.5+ , optparse-applicative >=0.14 && <0.15+ , seonbi+ else+ build-depends:+ cases ==0.1.3.2+ , html-charset >=0.1 && <0.2+ , optparse-applicative >=0.14 && <0.15+ , seonbi+ if flag(static)+ ld-options: -static+ if os(darwin) || os(windows)+ ghc-options: -Wall -fwarn-incomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N -static -optc-Os+ else+ ghc-options: -Wall -fwarn-incomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N -static -optl-static -optl-pthread -optc-Os -fPIC+ else+ ghc-options: -Wall -fwarn-incomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N+ default-language: Haskell2010++executable seonbi-api+ main-is: seonbi-api.hs+ other-modules:+ Paths_seonbi+ hs-source-dirs:+ app+ build-depends:+ aeson >=1.3.1 && <1.5+ , base >=4.7 && <5+ , bytestring+ , containers+ , http-types >=0.12 && <0.13+ , optparse-applicative >=0.14 && <0.15+ , seonbi+ , text+ , wai >=3.2 && <3.3+ , warp >=3.2 && <3.3+ if os(darwin)+ ghc-options: -Wall -fprint-explicit-kinds -optP-Wno-nonportable-include-path+ else+ ghc-options: -Wall -fprint-explicit-kinds+ if flag(static)+ ld-options: -static+ if os(darwin) || os(windows)+ ghc-options: -Wall -fwarn-incomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N -static -optc-Os+ else+ ghc-options: -Wall -fwarn-incomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N -static -optl-static -optl-pthread -optc-Os -fPIC+ else+ ghc-options: -Wall -fwarn-incomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N+ default-language: Haskell2010++test-suite doctest+ type: exitcode-stdio-1.0+ main-is: doctest.hs+ hs-source-dirs:+ test+ ghc-options: -threaded+ build-depends:+ QuickCheck+ , aeson >=1.3.1 && <1.5+ , base >=4.7 && <5+ , bytestring+ , containers+ , doctest+ , doctest-discover+ , seonbi+ , text+ , unicode-show+ if os(darwin)+ ghc-options: -Wall -fprint-explicit-kinds -optP-Wno-nonportable-include-path+ else+ ghc-options: -Wall -fprint-explicit-kinds+ default-language: Haskell2010++test-suite hlint+ type: exitcode-stdio-1.0+ main-is: hlint.hs+ hs-source-dirs:+ test+ ghc-options: -threaded+ build-depends:+ aeson >=1.3.1 && <1.5+ , base >=4.7 && <5+ , bytestring+ , containers+ , hlint >=2.1.7 && <2.2+ , text+ if os(darwin)+ ghc-options: -Wall -fprint-explicit-kinds -optP-Wno-nonportable-include-path+ else+ ghc-options: -Wall -fprint-explicit-kinds+ default-language: Haskell2010++test-suite spec+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ other-modules:+ Text.Seonbi.FacadeSpec+ Text.Seonbi.HangulSpec+ Text.Seonbi.HanjaSpec+ Text.Seonbi.Html.ClipperSpec+ Text.Seonbi.Html.PreservationSpec+ Text.Seonbi.Html.PrinterSpec+ Text.Seonbi.Html.ScannerSpec+ Text.Seonbi.Html.TextNormalizerSpec+ Text.Seonbi.Html.WrapperSpec+ Text.Seonbi.PunctuationSpec+ Text.Seonbi.Unihan.KHangulSpec+ Paths_seonbi+ hs-source-dirs:+ test+ ghc-options: -Wno-incomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ aeson >=1.3.1 && <1.5+ , base >=4.7 && <5+ , bytestring+ , containers+ , hspec >=2.4.8 && <3+ , hspec-discover >=2.4.8 && <3+ , seonbi+ , text+ if os(darwin)+ ghc-options: -Wall -fprint-explicit-kinds -optP-Wno-nonportable-include-path+ else+ ghc-options: -Wall -fprint-explicit-kinds+ default-language: Haskell2010
+ src/Text/Seonbi/Facade.hs view
@@ -0,0 +1,335 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+-- | Provides higher-level APIs. Read 'transformHtmlText' function first,+-- and then see also 'Configuration' type.+module Text.Seonbi.Facade+ ( ArrowOption (..)+ , CiteOption (..)+ , Configuration (..)+ , HanjaDictionary+ , HanjaOption (..)+ , HanjaReadingOption (..)+ , HanjaRenderingOption (..)+ , QuoteOption (..)+ , ko_KP+ , ko_KR+ , presets+ , readDictionaryFile+ , southKoreanDictionary+ , transformHtmlText+ , transformHtmlLazyText+ ) where++import Data.Char+import Data.Maybe+import Data.String (IsString)+import GHC.Exts (IsList (toList))+import GHC.Generics (Generic)+import System.IO.Error+import System.IO.Unsafe++import Data.ByteString.Lazy+import Data.Csv+import Data.Map.Strict+import Data.Set+import Data.Text+import qualified Data.Text.Lazy as LT+import System.FilePath ((</>))++import Paths_seonbi (getDataDir)+import Text.Seonbi.Hanja+import Text.Seonbi.Html+import Text.Seonbi.Punctuation+import Text.Seonbi.Trie as Trie++-- | Transformation settings. For the most cases, you could use one of+-- presets:+--+-- - 'ko_KR'+-- - 'ko_KP'+data Monad m => Configuration m a = Configuration + { -- | An optional debugging logger to print its internal AST.+ debugLogger :: Maybe (HtmlEntity -> m a)+ -- | Whether to take and result in XHTML instead of HTML.+ , xhtml :: Bool+ -- | An option to decide how quotation marks are rendered.+ -- If 'Nothing' no quotes are transformed.+ , quote :: Maybe QuoteOption+ -- | An option to transform folk-citing quotes (e.g., @\<\<한겨레\>\>@)+ -- into proper citing quotes (e.g., @《한겨레》).+ , cite :: Maybe CiteOption+ -- | Settings to transform arrow-looking punctuations into proper arrows.+ -- If 'Nothing' no arrows are transformed.+ , arrow :: Maybe ArrowOption+ -- | Whether to transform triple periods into a proper ellipsis.+ , ellipsis :: Bool+ -- | Whether to transform folk em dashes into proper em dashes.+ , emDash :: Bool+ -- | Settings to deal with Sino-Korean words.+ , hanja :: Maybe HanjaOption+ }++instance Monad m => Show (Configuration m a) where+ show c = "Configuration {\n" <>+ " debugLogger = " <>+ maybe "Nothing" (const "Just ...") (debugLogger c) <> "," <>+ " xhtml = " <> show (xhtml c) <> "," <>+ " quote = " <> show (quote c) <> "," <>+ " arrow = " <> show (cite c) <> "," <>+ " cite = " <> show (arrow c) <> "," <>+ " ellipsis = " <> show (ellipsis c) <> "," <>+ " emDash = " <> show (emDash c) <> "," <>+ " hanja = " <> show (hanja c) <>+ "}"++-- | An option to decide how quotation marks are rendered.+data QuoteOption+ -- | English-style curved quotes (@‘@: U+2018, @’@: U+2019, @“@: U+201C,+ -- @”@: U+201D), which are used by South Korean orthography.+ = CurvedQuotes+ -- | East Asian guillemets (@〈@: U+3008, @〉@: U+3009, @《@: U+300A, @》@:+ -- U+300B), which are used by North Korean orthography.+ | Guillemets + -- | Use English-style curved quotes (@‘@: U+2018, @’@: U+2019) for single+ -- quotes, and HTML @\<q\>@ tags for double quotes.+ | CurvedSingleQuotesWithQ + deriving (Enum, Eq, Generic, Read, Show)++-- | An option to transform folk-citing quotes (e.g., @\<\<한겨레\>\>@) into+-- proper citing quotes (e.g., @《한겨레》@).+data CiteOption+ -- | Cite a title using angle quotes, used by South Korean orthography in+ -- horizontal writing (橫書), e.g., 《나비와 엉겅퀴》 or 〈枾崎의 바다〉.+ = AngleQuotes+ -- | Cite a title using corner brackets, used by South Korean orthography in+ -- vertical writing (縱書) and Japanese orthography,+ -- e.g., 『나비와 엉겅퀴』 or 「枾崎의 바다」.+ | CornerBrackets+ -- | Same as 'AngleQuotes' except it wraps the title with a @\<cite\>@ tag.+ | AngleQuotesWithCite+ -- | Same as 'CornerBrackets' except it wraps the title with+ -- a @\<cite\>@ tag.+ | CornerBracketsWithCite+ deriving (Enum, Eq, Generic, Read, Show)++-- | Settings to transform arrow-looking punctuations into proper arrows.+data ArrowOption = ArrowOption+ { -- | Whether to transform bi-directional arrows as well as+ -- left/rightwards arrows.+ bidirArrow :: Bool+ -- | Whether to transform double arrows as well as single arrows.+ , doubleArrow :: Bool+ } deriving (Eq, Generic, Show)++-- | Settings to deal with Sino-Korean words.+data HanjaOption = HanjaOption+ { -- | How to render Sino-Korean words.+ rendering :: HanjaRenderingOption+ -- | How to rewrite Sino-Korean words in hangul.+ , reading :: HanjaReadingOption+ } deriving (Show)++-- | Available options to render Sino-Korean words.+data HanjaRenderingOption+ -- | Renders a word in hangul-only, no hanja at all (e.g., @안녕히@).+ = HangulOnly+ -- | Renders a word in hangul followed by hanja in parentheses+ -- (e.g., @안녕(安寧)히@).+ | HanjaInParentheses+ -- | Renders words in hangul-only for the most part, and if there are+ -- homophones in a document put their hanja notation in parentheses+ -- (e.g., @안녕히@ or @소수(小數)와 소수(素數)@).+ | DisambiguatingHanjaInParentheses+ -- | Renders a word in @<ruby>@ tag (e.g.,+ -- @\<ruby\>安寧\<rp\>(\<\/rp\>\<rt\>안녕\<\/rt\>\<rp\>)\<\/rp\>\<\/ruby\>히@).+ --+ -- Please read [Use Cases & Exploratory Approaches for Ruby+ -- Markup](https://www.w3.org/TR/ruby-use-cases/) as well for more+ -- information.+ | HanjaInRuby+ deriving (Enum, Eq, Generic, Read, Show)++-- | Settings to read Sino-Korean words.+data HanjaReadingOption = HanjaReadingOption+ { -- | Whether to apply Initial Sound Law (頭音法則) or not.+ initialSoundLaw :: Bool+ -- | A dictionary which has hanja readings. Keys are+ -- hanja words and values are their corresponding hangul readings,+ -- e.g.:+ --+ -- > [("敗北", "패배"), ("北極", "북극")] :: HanjaDictionary+ , dictionary :: HanjaDictionary+ }++instance Show HanjaReadingOption where+ show HanjaReadingOption { dictionary, initialSoundLaw } =+ "HanjaReadingOption {" <>+ " dictionary = [" <>+ show (Trie.size dictionary) <>+ " words]," <>+ " initialSoundLaw = " <>+ show initialSoundLaw <>+ " }"++-- | Transforms a given HTML text. 'Nothing' if it fails to parse the given+-- HTML text.+transformHtmlText :: Monad m => Configuration m a -> Text -> m Text+transformHtmlText config =+ fmap LT.toStrict . transformHtmlLazyText config . LT.fromStrict++-- | A lazy version of 'transformHtmlText' function.+transformHtmlLazyText :: Monad m => Configuration m a -> LT.Text -> m LT.Text+transformHtmlLazyText config@Configuration { xhtml, debugLogger } htmlText =+ case scanHtml htmlText of+ Done "" input -> do+ case debugLogger of+ Just logger -> mapM_ logger input+ Nothing -> return ()+ return $ printHtml' $ toTransformer config input+ _ ->+ fail "failed to parse input"+ where+ printHtml' :: [HtmlEntity] -> LT.Text+ printHtml'+ | xhtml = printXhtml+ | otherwise = printHtml++toTransformers :: Monad m => Configuration m a -> [[HtmlEntity] -> [HtmlEntity]]+toTransformers Configuration { quote, cite, arrow, ellipsis, emDash, hanja } =+ [ case quote of+ Nothing -> id+ Just quoteOption -> transformQuote $+ case quoteOption of+ CurvedQuotes -> curvedQuotes+ Guillemets -> guillemets+ CurvedSingleQuotesWithQ -> curvedSingleQuotesWithQ+ , case cite of+ Nothing -> id+ Just citeOption -> quoteCitation $+ case citeOption of+ AngleQuotes -> angleQuotes { htmlElement = Nothing }+ CornerBrackets -> cornerBrackets { htmlElement = Nothing }+ AngleQuotesWithCite -> angleQuotes+ CornerBracketsWithCite -> cornerBrackets+ , case arrow of+ Nothing -> id+ Just ArrowOption { bidirArrow, doubleArrow } -> transformArrow $+ Data.Set.fromList $ catMaybes+ [ if bidirArrow then Just LeftRight else Nothing+ , if doubleArrow then Just DoubleArrow else Nothing+ ]+ , if ellipsis then transformEllipsis else id+ , if emDash then transformEmDash else id+ , case hanja of+ Nothing ->+ id+ Just HanjaOption+ { rendering+ , reading = HanjaReadingOption { initialSoundLaw, dictionary }+ } ->+ phoneticizeHanja $ def+ { phoneticizer =+ let withDict = if Trie.null dictionary+ then id+ else withDictionary dictionary+ phoneticize = if initialSoundLaw+ then phoneticizeHanjaWordWithInitialSoundLaw+ else phoneticizeHanjaWord+ in+ withDict phoneticize+ , wordRenderer = case rendering of+ HangulOnly -> hangulOnly+ HanjaInParentheses -> hanjaInParentheses+ DisambiguatingHanjaInParentheses -> hangulOnly+ HanjaInRuby -> hanjaInRuby+ , homophoneRenderer = case rendering of+ HangulOnly -> hangulOnly+ HanjaInParentheses -> hanjaInParentheses+ DisambiguatingHanjaInParentheses -> hanjaInParentheses+ HanjaInRuby -> hanjaInRuby+ }+ ]++toTransformer :: Monad m => Configuration m a -> [HtmlEntity] -> [HtmlEntity]+toTransformer =+ Prelude.foldl (.) id . toTransformers++-- | Preset 'Configuration' for South Korean orthography.+ko_KR :: Monad m => Configuration m a+ko_KR = Configuration+ { debugLogger = Nothing+ , quote = Just CurvedQuotes+ , cite = Just AngleQuotes+ , arrow = Just ArrowOption { bidirArrow = True, doubleArrow = True }+ , ellipsis = True+ , emDash = True+ , hanja = Just HanjaOption+ { rendering = DisambiguatingHanjaInParentheses+ , reading = HanjaReadingOption+ { dictionary = southKoreanDictionaryUnsafe+ , initialSoundLaw = True+ }+ }+ , xhtml = False+ }++-- | Preset 'Configuration' for North Korean orthography.+ko_KP :: Monad m => Configuration m a+ko_KP = ko_KR+ { quote = Just Guillemets+ , hanja = Just HanjaOption+ { rendering = HangulOnly+ , reading = HanjaReadingOption+ { dictionary = []+ , initialSoundLaw = False+ }+ }+ }++presets :: (Ord k, IsString k, Monad m) => Map k (Configuration m a)+presets =+ [ ("ko-kp", ko_KP)+ , ("ko-kr", ko_KR)+ ]++-- | Loads a dictionary file. The file consists of two-column TSV+-- (tab-separated values); the first column is hanja and the second column is+-- hangul.+readDictionaryFile :: FilePath -> IO HanjaDictionary+readDictionaryFile path = do+ byteString <- Data.ByteString.Lazy.readFile path+ case decodeWith tsvDecodeOptions NoHeader byteString of+ Right vector -> return $ Prelude.foldl+ (\ d (DictionaryPair k v) -> Trie.insert k v d)+ Trie.empty+ (GHC.Exts.toList vector)+ Left err -> fail err+ where+ tsvDecodeOptions :: DecodeOptions+ tsvDecodeOptions = defaultDecodeOptions+ { decDelimiter = fromIntegral (ord '\t')+ }++{-# NOINLINE southKoreanDictionaryUnsafe #-}+southKoreanDictionaryUnsafe :: HanjaDictionary+southKoreanDictionaryUnsafe =+ unsafePerformIO $ ignoreError southKoreanDictionary+ where+ ignoreError :: IO HanjaDictionary -> IO HanjaDictionary+ ignoreError action =+ catchIOError action $ const $ return Trie.empty++-- | Loads [Standard Korean Language Dictionary](https://stdict.korean.go.kr/)+-- (標準國語大辭典) data.+southKoreanDictionary :: IO HanjaDictionary+southKoreanDictionary = do+ dataDir <- getDataDir+ readDictionaryFile (dataDir </> "ko-kr-stdict.tsv")++data DictionaryPair = DictionaryPair !Text !Text deriving (Generic, Show)++instance FromRecord DictionaryPair++{- HLINT ignore "Use camelCase" -}
+ src/Text/Seonbi/Hangul.hs view
@@ -0,0 +1,88 @@+module Text.Seonbi.Hangul+ ( JamoTriple+ , fromJamoTriple+ , isHangulSyllable+ , toJamoTriple+ ) where++-- $setup+-- >>> import qualified Text.Show.Unicode+-- >>> :set -interactive-print=Text.Show.Unicode.uprint++-- | A triple of an initial consonant, a vowel, and an optional final consonant.+type JamoTriple = (Char, Char, Maybe Char)++-- | Checks if a character is a hangul letter and a complete syllable.+--+-- >>> isHangulSyllable '가'+-- True+-- >>> isHangulSyllable 'ㄱ'+-- False+isHangulSyllable :: Char -> Bool+isHangulSyllable c =+ c >= '\xac00' && c <= '\xd7a3';++syllableBase :: Int+syllableBase = 0xac00++initialBase :: Int+initialBase = 0x1100++vowelBase :: Int+vowelBase = 0x1161++finalBase :: Int+finalBase = 0x11a7++vowelCount :: Int+vowelCount = 21;++finalCount :: Int+finalCount = 28;++-- | Takes a complete hangul syllable apart into consonants and a vowel.+-- Returns 'Nothing' for non-hangul letters.+--+-- >>> toJamoTriple '가'+-- Just ('ᄀ','ᅡ',Nothing)+-- >>> toJamoTriple '글'+-- Just ('ᄀ','ᅳ',Just 'ᆯ')+-- >>> toJamoTriple 'A'+-- Nothing+toJamoTriple :: Char -> Maybe JamoTriple+toJamoTriple c+ | isHangulSyllable c = Just+ ( toEnum $ initialBase + ((syllable `div` finalCount) `div` vowelCount)+ , toEnum $ vowelBase + ((syllable `div` finalCount) `mod` vowelCount)+ , case syllable `mod` finalCount of+ 0 -> Nothing+ f -> Just $ toEnum (finalBase + f)+ )+ | otherwise = Nothing+ where+ syllable :: Int+ syllable = fromEnum c - syllableBase++-- | Composes hangul jamo triple into a hangul syllable.+--+-- >>> fromJamoTriple ('ᄀ', 'ᅡ', Nothing)+-- Just '가'+-- >>> fromJamoTriple ('ᄀ', 'ᅳ', Just 'ᆯ')+-- Just '글'+fromJamoTriple :: JamoTriple -> Maybe Char+fromJamoTriple (initial, vowel, final)+ | initialIndex < 0 = Nothing+ | initialIndex > 18 = Nothing+ | vowelIndex < 0 = Nothing+ | vowelIndex > 20 = Nothing+ | finalIndex < 0 = Nothing+ | finalIndex > 27 = Nothing+ | otherwise = Just $ toEnum $ syllableBase ++ (initialIndex * vowelCount + vowelIndex) * finalCount + finalIndex+ where+ initialIndex :: Int+ initialIndex = fromEnum initial - initialBase+ vowelIndex :: Int+ vowelIndex = fromEnum vowel - vowelBase+ finalIndex :: Int+ finalIndex = maybe 0 (\ f -> fromEnum f - finalBase) final
+ src/Text/Seonbi/Hanja.hs view
@@ -0,0 +1,549 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NamedFieldPuns #-}+module Text.Seonbi.Hanja+ ( HanjaDictionary+ , HanjaPhoneticization (..)+ , HanjaWordPhoneticizer+ , HanjaWordRenderer+ , convertInitialSoundLaw+ , def+ , hangulOnly+ , hanjaInParentheses+ , hanjaInRuby+ , initialSoundLawTable+ , initialSoundLawTable'+ , phoneticizeHanja+ , phoneticizeHanjaChar+ , phoneticizeHanjaWord+ , phoneticizeHanjaWordWithInitialSoundLaw+ , revertInitialSoundLaw+ , withDictionary+ ) where++import Prelude hiding (lookup)++import Control.Applicative+import Control.Monad+import Data.Char+import Data.List hiding (lookup)+import Data.Maybe+import Data.Ord (comparing)++import Data.Attoparsec.Text+import Data.Default+import Data.Map.Strict+import Data.Set+import Data.Text hiding (concatMap)++import Text.Seonbi.Hangul+import Text.Seonbi.Html+import Text.Seonbi.Html.Preservation+import Text.Seonbi.Html.TagStack (push)+import qualified Text.Seonbi.Trie as Trie+import Text.Seonbi.Unihan.KHangul++-- $setup+-- >>> import qualified Text.Show.Unicode+-- >>> :set -interactive-print=Text.Show.Unicode.uprint++data HanjaPhoneticization = HanjaPhoneticization+ { -- | A function to phoneticize a hanja word.+ -- Use 'phoneticizeHanjaWordWithInitialSoundLaw' for South Korean+ -- orthography, or 'phoneticizeHanjaWord' for North Korean orthography.+ phoneticizer :: HanjaWordPhoneticizer+ -- | A function to render a hanja word. See also 'HanjaWordRenderer'.+ , wordRenderer :: HanjaWordRenderer+ -- | A function to render a hanja word which should be disambiguated.+ -- It's used instead of 'wordRenderer' when two or more words in+ -- a text have the same hangul reading but actually are dictinct+ -- each other in hanja characters, e.g., 小數/素數 (소수).+ , homophoneRenderer :: HanjaWordRenderer+ -- | Whether to insert some HTML comments that contain useful information+ -- for debugging into the result. This does not affect the rendering+ -- of the result HTML, but only the HTML code.+ , debugComment :: Bool+ }++-- | A function to phoneticize a Sino-Korean (i.e., hanja) word (漢字語)+-- into hangul letters.+-- See also 'phoneticizeHanjaWord', 'phoneticizeHanjaWordWithInitialSoundLaw',+-- and 'withDictionary'.+type HanjaWordPhoneticizer+ = Text -- ^ A Sino-Korean (i.e., hanja) word (漢字語) to phoneticize.+ -> Text -- ^ Hangul letters that phoneticize the given Sino-Korean word.++-- | A function to render a Sino-Korean (i.e., hanja) word (漢字語).+-- Choose one in 'hangulOnly', 'hanjaInParentheses', and 'hanjaInRuby'.+type HanjaWordRenderer+ = HtmlTagStack+ -- ^ Where rendered HTML entities get interleaved into.+ -> Text+ -- ^ A Sino-Korean (i.e., hanja) word (漢字語) to render.+ -> Text+ -- ^ Hangul letters that phoneticized the Sino-Korean word.+ -> [HtmlEntity]+ -- ^ Rendered HTML entities.++-- | Renders a word in hangul-only, no hanja at all (e.g., @안녕히@).+hangulOnly :: HanjaWordRenderer+hangulOnly stack _ hangul = [HtmlCdata stack hangul]++-- | Renders a word in hangul followed by hanja in parentheses+-- (e.g., @안녕(安寧)히@).+hanjaInParentheses :: HanjaWordRenderer+hanjaInParentheses stack hanja hangul =+ [HtmlCdata stack $ Data.Text.concat [hangul, "(", hanja, ")"]]++-- | Renders a word in @<ruby>@ tag (e.g.,+-- @\<ruby\>安寧\<rp\>(\<\/rp\>\<rt\>안녕\<\/rt\>\<rp\>)\<\/rp\>\<\/ruby\>히@).+--+-- Please read [Use Cases & Exploratory Approaches for Ruby+-- Markup](https://www.w3.org/TR/ruby-use-cases/) as well for more information.+hanjaInRuby :: HanjaWordRenderer+hanjaInRuby stack hanja hangul =+ [ HtmlStartTag stack Ruby ""+ , HtmlCdata rubyStack hanja+ , HtmlStartTag rubyStack RP ""+ , HtmlText (push RP rubyStack) "("+ , HtmlEndTag rubyStack RP+ , HtmlStartTag rubyStack RT ""+ , HtmlCdata (push RT rubyStack) hangul+ , HtmlEndTag rubyStack RT+ , HtmlStartTag rubyStack RP ""+ , HtmlText (push RP rubyStack) ")"+ , HtmlEndTag rubyStack RP+ , HtmlEndTag stack Ruby+ ]+ where+ rubyStack :: HtmlTagStack+ rubyStack = push Ruby stack++instance Default HanjaPhoneticization where+ def = HanjaPhoneticization+ { phoneticizer = phoneticizeHanjaWordWithInitialSoundLaw+ , wordRenderer = hangulOnly+ , homophoneRenderer = hanjaInParentheses+ , debugComment = False+ }++-- | Transforms hanja words in the given HTML entities into corresponding+-- hangul words.+phoneticizeHanja+ :: HanjaPhoneticization+ -- ^ Configures the phoneticization details.+ -> [HtmlEntity]+ -- ^ HTML entities (that may contain some hanja words) to phoneticize+ -- all hanja words into corresponding hangul-only words.+ -> [HtmlEntity]+ -- ^ HTML entities that have no hanja words but hangul-only words instead.+phoneticizeHanja HanjaPhoneticization { phoneticizer+ , wordRenderer+ , homophoneRenderer+ , debugComment+ }+ entities =+ (`concatMap` normalized) $ \ case+ Left e' ->+ [e']+ Right (stack, hanja, hangul) ->+ if Data.Set.size (findWithDefault [] hangul frequencyDict) > 1+ then homophoneRenderer' stack hanja hangul+ else wordRenderer' stack hanja hangul+ where+ frequencyDict :: Map Text (Set Text)+ frequencyDict = Data.Map.Strict.fromListWith+ Data.Set.union+ [(hangul, [hanja]) | Right (_, hanja, hangul) <- normalized]+ normalized :: [Either HtmlEntity (HtmlTagStack, Text, Text)]+ normalized = Data.List.concat+ [ case e of+ Left _ ->+ [e]+ Right (stack, hanja, hangul) ->+ let hanjaWords = splitByDigits hanja+ hangulWords = splitByDigits hangul+ hanjaWordsLen = Prelude.length hanjaWords+ hangulWordsLen = Prelude.length hangulWords+ in+ if hanjaWordsLen /= hangulWordsLen+ then [e]+ else+ [ if Data.Text.any isDigit hanj+ then Left $ HtmlText stack hanj+ else Right (stack, hanj, hang)+ | (hanj, hang) <- Prelude.zip hanjaWords hangulWords+ ]+ | e <- concatMap transform entities+ ]+ splitByDigits :: Text -> [Text]+ splitByDigits = Data.Text.groupBy (\ a b -> isDigit a == isDigit b)+ transform :: HtmlEntity -> [Either HtmlEntity (HtmlTagStack, Text, Text)]+ transform entity@HtmlText { tagStack = tagStack', rawText = rawText' }+ | isPreservedTagStack tagStack' =+ [Left entity]+ | otherwise =+ case analyzeHanjaText rawText' of+ Nothing -> [Left $ entity { rawText = rawText' }]+ Just pairs ->+ [ if trueIfHanja+ then Right (tagStack', htmlText, phoneticizer htmlText)+ else Left (entity { rawText = htmlText })+ -- Note that htmlText here can have HTML entities.+ | (trueIfHanja, htmlText) <- pairs+ ]+ transform entity =+ [Left entity]+ -- FIXME: This should be public:+ debugRenderer :: HanjaWordRenderer -> HanjaWordRenderer+ debugRenderer render stack hanja hangul =+ HtmlComment stack (" Hanja: " `append` hanja)+ : render stack hanja hangul ++ [HtmlComment stack " /Hanja "]+ wordRenderer' :: HanjaWordRenderer+ wordRenderer'+ | debugComment = debugRenderer wordRenderer+ | otherwise = wordRenderer+ homophoneRenderer' :: HanjaWordRenderer+ homophoneRenderer'+ | debugComment = debugRenderer homophoneRenderer+ | otherwise = homophoneRenderer++analyzeHanjaText :: Text -> Maybe [(Bool, Text)]+analyzeHanjaText text' =+ case parseOnly (textParser <* endOfInput) text' of+ Left _ -> Nothing+ Right pairs -> Just+ [ (trueIfHanja, text)+ | (trueIfHanja, text) <- pairs+ , not (Data.Text.null text)+ ]++-- | Reads a hanja word and returns a corresponding hangul word.+--+-- >>> :set -XOverloadedStrings+-- >>> phoneticizeHanjaWord "漢字"+-- "한자"+--+-- Note that it does not apply Initial Sound Law (頭音法則):+--+-- >>> phoneticizeHanjaWord "來日"+-- "래일"+phoneticizeHanjaWord :: HanjaWordPhoneticizer+phoneticizeHanjaWord =+ Data.Text.map phoneticizeHanjaChar++-- | It is like 'phoneticizeHanjaWord', but it also applies+-- Initial Sound Law (頭音法則).+--+-- >>> :set -XOverloadedStrings+-- >>> phoneticizeHanjaWordWithInitialSoundLaw "來日"+-- "내일"+-- >>> phoneticizeHanjaWordWithInitialSoundLaw "未來"+-- "미래"+phoneticizeHanjaWordWithInitialSoundLaw :: HanjaWordPhoneticizer+phoneticizeHanjaWordWithInitialSoundLaw word =+ case parseOnly (parser <* endOfInput) word of+ Left _ -> word+ Right "" -> word+ Right hangulWord -> hangulWord+ where+ parser :: Parser Text+ parser = do+ chars <- many'+ ( try yeolYul+ <|> try prefixedNumber+ <|> try hanNumber+ <|> try (Data.Text.singleton . phoneticize <$> anyChar)+ )+ let hangulWord = Data.Text.concat chars+ return $ Data.Text.concat+ [ Data.Text.map convertInitialSoundLaw $ Data.Text.take 1 hangulWord+ , Data.Text.drop 1 hangulWord+ ]+ yeolYul :: Parser Text+ yeolYul = do+ former <- satisfy $ \ c ->+ c `hasBatchim` Just '\x11ab' || c `hasBatchim` Nothing+ later <- phone '렬' <|> phone '률'+ return $ pack+ [ phoneticize former+ , convert later+ ]+ prefixedNumber :: Parser Text+ prefixedNumber = do+ prefix <- char '第'+ digits <- takeWhile1 isHanDigit+ return $ Data.Text.cons+ (phoneticize prefix)+ (Data.Text.map convertDigit digits)+ hanNumber :: Parser Text+ hanNumber = do+ first <- hanDigit+ rest <- takeWhile1 isHanDigit+ return $ Data.Text.map convertDigit $ Data.Text.cons first rest+ hanDigit :: Parser Char+ hanDigit = satisfy isHanDigit+ phone :: Char -> Parser Char+ phone hangul = satisfy ((== hangul) . phoneticize)+ convertDigit :: Char -> Char+ convertDigit = convertInitialSoundLaw . phoneticizeDigit+ convert :: Char -> Char+ convert = convertInitialSoundLaw . phoneticize+ phoneticizeDigit :: Char -> Char+ phoneticizeDigit '參' = '삼'+ phoneticizeDigit '叁' = '삼'+ phoneticizeDigit '参' = '삼'+ phoneticizeDigit '叄' = '삼'+ phoneticizeDigit '拾' = '십'+ phoneticizeDigit c = phoneticize c+ phoneticize :: Char -> Char+ phoneticize = phoneticizeHanjaChar+ hasBatchim :: Char -> Maybe Char -> Bool+ hasBatchim c batchim =+ case toJamoTriple (phoneticize c) of+ Just (_, _, final) -> final == batchim+ _ -> False+ isHanDigit :: Char -> Bool+ isHanDigit = inClass $+ "零一壹壱弌夁二貳贰弐弍貮三參叁参弎叄四肆䦉五伍六陸陆陸七柒漆八捌" +++ "九玖十拾百佰陌千仟阡萬万億兆京垓秭穰溝澗"++-- | Represents a dictionary that has hanja keys and values of their+-- corresponding hangul readings, e.g., @[("敗北", "패배")]@.+type HanjaDictionary = Trie.Trie Text++-- | Reads a hanja word according to the given dictionary, or falls back to+-- the other phoneticizer if there is no such word in the dictionary.+--+-- It's basically replace one with one:+--+-- >>> :set -XOverloadedLists -XOverloadedStrings+-- >>> let phone = withDictionary [("自轉車", "자전거")] phoneticizeHanjaWord+-- >>> phone "自轉車"+-- "자전거"+--+-- But, if it faces any words or characters that are not registered in+-- the dictionary, it does the best to interpolate prefixes/infixes/suffixes+-- using the fallback phoneticizer:+--+-- >>> phone "自轉車道路"+-- "자전거도로"+-- >>> phone "二輪自轉車"+-- "이륜자전거"+withDictionary+ :: HanjaDictionary+ -- ^ Hangul readings of Sino-Korean words.+ -> HanjaWordPhoneticizer+ -- ^ A fallback phoneticize for unregistered words.+ -- E.g., 'phoneticizeHanjaWordWithInitialSoundLaw'.+ -> HanjaWordPhoneticizer+ -- ^ A combined phoneticizer.+withDictionary _ _ "" = ""+withDictionary dic fallback word =+ case matches of+ [] ->+ fallback word+ (replaced, rest) : _ ->+ if Data.Text.null rest+ then replaced+ else replaced `append` withDictionary dic fallback rest+ where+ lookupDic :: Text -> Maybe Text+ lookupDic = (`Trie.lookup` dic)+ tries :: [(Text, Text)]+ tries =+ [Data.Text.splitAt pos word | pos <- [0..Data.Text.length word]]+ patterns :: Text -> [Text]+ patterns word' =+ word' : case unsnoc word' of+ Just (next, _) -> patterns next+ Nothing -> []+ matchTries :: [Maybe (Text, Text, Text)]+ matchTries =+ (`Prelude.map` tries) $ \ (unmatched, wd) ->+ case [(p, m) | p <- patterns wd, m <- maybeToList (lookupDic p)] of+ [] -> Nothing+ pair : _ -> Just+ ( unmatched+ , snd pair+ , Data.Text.drop (Data.Text.length $ fst pair) wd+ )+ matches :: [(Text, Text)]+ matches =+ [ (fallback unmatched `append` matched, rest)+ | Just (unmatched, matched, rest) <- matchTries+ ]++-- | Reads a hanja character as a hangul character.+--+-- >>> phoneticizeHanjaChar '漢'+-- '한'+--+-- Note that it does not follow Initial Sound Law (頭音法則):+--+-- >>> phoneticizeHanjaChar '六'+-- '륙'+phoneticizeHanjaChar :: Char -> Char+phoneticizeHanjaChar c = fromMaybe c $ do+ readings <- lookup c kHangulData+ let readings' = Data.Map.Strict.toList readings+ let (sound, _) = minimumBy (comparing snd) readings'+ let initialLawReverted = Data.Set.filter+ (`Data.Map.Strict.member` readings)+ (revertInitialSoundLaw sound)+ return $ case Data.Set.toList initialLawReverted of+ [] -> sound+ reverted : _ -> reverted++withoutBatchim :: Char -> Maybe (Char, Maybe Char)+withoutBatchim hangul = do+ (initial, vowel, final) <- toJamoTriple hangul+ noBatchim <- fromJamoTriple (initial, vowel, Nothing)+ return (noBatchim, final)++withBatchim :: Char -> Maybe Char -> Maybe Char+withBatchim hangul final = do+ (initial, vowel, _) <- toJamoTriple hangul+ fromJamoTriple (initial, vowel, final)++-- | Converts a hangul character according to Initial Sound Law (頭音法則).+--+-- >>> convertInitialSoundLaw '념'+-- '염'+--+-- If an input is not a hangul syllable or a syllable is not applicable to+-- the law it returns the given input without change:+--+-- >>> convertInitialSoundLaw 'A'+-- 'A'+-- >>> convertInitialSoundLaw '가'+-- '가'+convertInitialSoundLaw :: Char -> Char+convertInitialSoundLaw sound = fromMaybe sound $ do+ (pattern', final) <- withoutBatchim sound+ let converted = findWithDefault pattern' pattern' initialSoundLawTable+ withBatchim converted final++-- | It's a kind of inverse function of 'convertInitialSoundLaw',+-- except it returns a set of candidates instead of a single canonical answer+-- because Initial Sound Law (頭音法則) is not a bijective function.+--+-- >>> revertInitialSoundLaw '예'+-- fromList "례"+-- >>> revertInitialSoundLaw '염'+-- fromList "념렴"+--+-- It returns an empty set if an input is not applicable to the law:+--+-- >>> revertInitialSoundLaw '가'+-- fromList ""+revertInitialSoundLaw :: Char -> Set Char+revertInitialSoundLaw sound = fromMaybe Data.Set.empty $ do+ (pattern', final) <- withoutBatchim sound+ let candidates = Data.Set.toList $+ findWithDefault Data.Set.empty pattern' initialSoundLawTable'+ Just $ Data.Set.fromList $ catMaybes $ candidates <&> (`withBatchim` final)+ where+ (<&>) :: Functor f => f a -> (a -> b) -> f b+ (<&>) = flip fmap++textParser :: Parser [(Bool, Text)]+textParser = fmap Data.List.concat $ many' $ do+ -- We have 3 passes to optimize by utilizing takeWhile instead of many'+ hanjaEntities <- many' $ try $ do+ c <- unnamedCharRef+ unless (isHanjaOrDigit c) (fail "not a hanja")+ return c+ hanjaCharsText <- Data.Attoparsec.Text.takeWhile isHanjaOrDigit+ hanjaChars <- many' $ try $ do+ c <- unnamedCharRef <|> anyChar+ unless (isHanjaOrDigit c) (fail "not a hanja")+ return c+ -- Note that the parsed result can still have HTML entities; these+ -- are never touched.+ entities <- many' $ try $ do+ c <- unnamedCharRef+ when (isHanjaOrDigit c) (fail "a hanja")+ return c+ charsText <- takeTill isHanjaOrDigit+ chars <- many' $ try $ do+ c <- unnamedCharRef <|> anyChar+ when (isHanjaOrDigit c) (fail "a hanja")+ return c+ let hanjaText = Data.Text.concat+ [pack hanjaEntities, hanjaCharsText, pack hanjaChars]+ let text' = Data.Text.concat [pack entities, charsText, pack chars]+ when (Data.Text.null $ hanjaText `append` text') (fail "parsed nothing")+ return [(True, hanjaText), (False, text')]+ where+ isHanjaOrDigit :: Char -> Bool+ isHanjaOrDigit c =+ isDigit c || isHanja c+ isHanja :: Char -> Bool+ isHanja c =+ -- Ideographic Description Character+ '\x2f00' <= c && c <= '\x2fff' ||+ -- U+3007 IDEOGRAPHIC NUMBER ZERO (〇)+ '\x3007' == c ||+ -- CJK Unified Ideographs Extension A+ '\x3400' <= c && c <= '\x4dbf' ||+ -- CJK Unified Ideographs+ '\x4e00' <= c && c <= '\x9fcc' ||+ -- CJK Compatibility Ideographs+ '\xf900' <= c && c <= '\xfaff' ||+ -- CJK Unified Ideographs Extension B+ '\x20000' <= c && c <= '\x2a6d6' ||+ -- CJK Unified Ideographs Extension C+ '\x2a700' <= c && c <= '\x2b734' ||+ -- CJK Unified Ideographs Extension D+ '\x2b740' <= c && c <= '\x2b81d' ||+ -- CJK Unified Ideographs Extension E+ '\x2b820' <= c && c <= '\x2cea1' ||+ -- CJK Unified Ideographs Extension F+ '\x2ceb0' <= c && c <= '\x2ebe0' ||+ -- CJK Compatibility Ideographs Supplement+ '\x2f800' <= c && c <= '\x2fa1f'+ unnamedCharRef :: Parser Char+ unnamedCharRef = do+ _ <- char '&'+ _ <- char '#'+ hex <- option False ((char 'x' <|> char 'X') >> return True)+ codepoint <- if hex then hexadecimal else decimal+ _ <- char ';'+ return $ chr codepoint++-- | The Initial Sound Law (頭音法則) table according to South Korean+-- /Hangul Orthography/ (한글 맞춤법) Clause 5, Section 52, Chapter 6+-- (第6章52項5節). Keys are an original Sino-Korean sound and values+-- are a converted sound according to the law.+initialSoundLawTable :: Map Char Char+initialSoundLawTable =+ [ ('녀', '여')+ , ('뇨', '요')+ , ('뉴', '유')+ , ('니', '이')+ , ('랴', '야')+ , ('려', '여')+ , ('례', '예')+ , ('료', '요')+ , ('류', '유')+ , ('리', '이')+ , ('라', '나')+ , ('래', '내')+ , ('로', '노')+ , ('뢰', '뇌')+ , ('루', '누')+ , ('르', '느')+ ]++-- | Contains the same contents to 'initialSoundLawTable' except that+-- keys and values are crossed: keys are a converted sound and values are+-- possible original sounds.+initialSoundLawTable' :: Map Char (Set Char)+initialSoundLawTable' =+ foldrWithKey f Data.Map.Strict.empty initialSoundLawTable+ where+ f :: Char -> Char -> Map Char (Set Char) -> Map Char (Set Char)+ f original converted =+ insertWith Data.Set.union converted (Data.Set.singleton original)
+ src/Text/Seonbi/Html.hs view
@@ -0,0 +1,21 @@+module Text.Seonbi.Html+ ( HtmlEntity (..)+ , HtmlRawAttrs+ , HtmlTag (..)+ , HtmlTagKind (..)+ , HtmlTagStack+ , Result (..)+ , htmlTagKind+ , htmlTagName+ , normalizeText+ , printHtml+ , printXhtml+ , scanHtml+ ) where++import Text.Seonbi.Html.Entity+import Text.Seonbi.Html.Printer+import Text.Seonbi.Html.Scanner+import Text.Seonbi.Html.Tag+import Text.Seonbi.Html.TagStack+import Text.Seonbi.Html.TextNormalizer
+ src/Text/Seonbi/Html/Clipper.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE LambdaCase #-}+module Text.Seonbi.Html.Clipper+ ( clipPrefixText+ , clipSuffixText+ , clipText+ ) where++import Control.Monad+import Data.List (dropWhileEnd)++import Data.Text++import Text.Seonbi.Html++-- | Clip the given prefix text and suffix text from the HTML fragments.+-- It simply is composed of 'clipPrefixText' and 'clipSuffixText' functions.+-- It returns 'Nothing' if any of a prefix and a suffix does not match.+clipText :: Text -> Text -> [HtmlEntity] -> Maybe [HtmlEntity]+clipText prefix suffix =+ clipSuffixText suffix <=< clipPrefixText prefix++-- | Clip the given prefix text from the HTML fragments. If its first+-- text element does not have the same prefix, or the first element is not+-- an 'HtmlText' node, or the list of HTML fragments have nothing at all,+-- it returns 'Nothing'.+--+-- >>> :set -XOverloadedLists+-- >>> :set -XOverloadedStrings+-- >>> clipPrefixText "foo" [HtmlText [] "bar", HtmlStartTag [] P ""]+-- Nothing+-- >>> clipPrefixText "foo" [HtmlStartTag [] P "", HtmlText [] "foo"]+-- Nothing+-- >>> clipPrefixText "foo" []+-- Nothing+--+-- If the first element is an 'HtmlText' node, and its 'rawText' contains+-- the common prefix text, it returns a 'Just' value holding a list of+-- HTML fragments with the common prefix removed.+--+-- >>> clipPrefixText "foo" [HtmlText [] "foobar", HtmlStartTag [] P ""]+-- Just [HtmlText {... "bar"},HtmlStartTag {...}]+-- >>> clipPrefixText "foo" [HtmlText [] "foo", HtmlStartTag [] P ""]+-- Just [HtmlStartTag {..., tag = P, ...}]+--+-- A given text is treated as a raw text, which means even if some HTML+-- entities refer to the same characters it may fails to match unless+-- they share the exactly same representation, e.g.:+--+-- >>> clipPrefixText "&" [HtmlText [] "&"]+-- Nothing+--+-- In the same manner, it doesn't find a prefix from 'HtmlCdata', e.g.:+--+-- >>> clipPrefixText "foo" [HtmlCdata [] "foo", HtmlStartTag [] P ""]+-- Nothing+--+-- In order to remove a prefix from both 'HtmlText' and 'HtmlCdata',+-- apply 'normalizeText' first so that all 'HtmlCdata' entities are transformed+-- to equivalent 'HtmlText' entities:+--+-- >>> import Text.Seonbi.Html.TextNormalizer (normalizeText)+-- >>> let normalized = normalizeText [HtmlCdata [] "foo", HtmlStartTag [] P ""]+-- >>> clipPrefixText "foo" normalized+-- Just [HtmlStartTag {..., tag = P, ...}]+--+-- Plus, it works even if HTML fragments contain some 'HtmlComment' entities,+-- but these are not touched at all, e.g.:+--+-- >>> clipPrefixText "bar" [HtmlComment [] "foo", HtmlText [] "barbaz"]+-- Just [HtmlComment {... "foo"},HtmlText {... "baz"}]+clipPrefixText :: Text -> [HtmlEntity] -> Maybe [HtmlEntity]+clipPrefixText prefix []+ | Data.Text.null prefix = Just []+ | otherwise = Nothing+clipPrefixText prefix (x@HtmlComment {} : xs) =+ (x :) <$> clipPrefixText prefix xs+clipPrefixText prefix (x@HtmlText { rawText = rawText' } : xs)+ | prefix == rawText' = Just xs+ | prefix `isPrefixOf` rawText' = Just $+ x { rawText = Data.Text.drop (Data.Text.length prefix) rawText' } : xs+ | otherwise = Nothing+clipPrefixText _ _ = Nothing++-- | Clip the given suffix text from the HTML fragments, in the same manner+-- to 'clipPrefixText'.+clipSuffixText :: Text -> [HtmlEntity] -> Maybe [HtmlEntity]+clipSuffixText suffix []+ | Data.Text.null suffix = Just []+ | otherwise = Nothing+clipSuffixText suffix entities =+ case Prelude.last entities' of+ e@HtmlText { rawText = rawText' }+ | suffix == rawText' -> Just (init' ++ comments)+ | suffix `isSuffixOf` rawText' ->+ let+ sLen = Data.Text.length suffix+ rtLen = Data.Text.length rawText'+ clipped = Data.Text.take (rtLen - sLen) rawText'+ in+ Just (init' ++ e { rawText = clipped } : comments)+ | otherwise -> Nothing+ _ -> Nothing+ where+ entities' :: [HtmlEntity]+ entities' = (`Data.List.dropWhileEnd` entities) $ \ case+ HtmlComment {} -> True+ _ -> False+ init' :: [HtmlEntity]+ init' = Prelude.init entities'+ comments :: [HtmlEntity]+ comments = Prelude.drop (Prelude.length entities') entities
+ src/Text/Seonbi/Html/Entity.hs view
@@ -0,0 +1,64 @@+module Text.Seonbi.Html.Entity+ ( HtmlEntity (..)+ , HtmlRawAttrs+ ) where++import Data.Text++import Text.Seonbi.Html.Tag (HtmlTag)+import Text.Seonbi.Html.TagStack (HtmlTagStack)++type HtmlRawAttrs = Text++-- | An event entity emitted by 'scanHtml'.+data HtmlEntity+ -- | Represent a token which [opens an HTML element+ -- ](https://www.w3.org/TR/html5/syntax.html#start-tags).+ --+ -- Note that 'rawAttributes' is not a parsed and structured data but a raw+ -- string as its name implies.+ --+ -- The 'tagStack' doesn't include the corresponding opened 'tag'.+ = HtmlStartTag+ { -- | A stack of 'HtmlTag's that represents a hierarchy of a currently+ -- parsing position in an 'HtmlTag' tree.+ tagStack :: HtmlTagStack+ , tag :: HtmlTag+ , rawAttributes :: HtmlRawAttrs+ }+ -- | Represent a token which [closes an HTML element+ -- ](https://www.w3.org/TR/html5/syntax.html#end-tags).+ -- The 'tagStack' doesn't include the corresponding closed 'tag'.+ | HtmlEndTag+ { -- | A stack of 'HtmlTag's that represents a hierarchy of a currently+ -- parsing position in an 'HtmlTag' tree.+ tagStack :: HtmlTagStack+ , tag :: HtmlTag+ }+ -- | Represent a token of a text node. Note that 'rawText' is not a parsed+ -- and structured data but a raw string as its name implies. There can be+ -- continuously more than one 'HtmlText' values can be emitted even if they+ -- are not separated by element openings or closings.+ | HtmlText+ { -- | A stack of 'HtmlTag's that represents a hierarchy of a currently+ -- parsing position in an 'HtmlTag' tree.+ tagStack :: HtmlTagStack+ , rawText :: Text+ }+ -- | Represent a token of a+ -- [CDATA section](https://www.w3.org/TR/html5/syntax.html#cdata-sections).+ | HtmlCdata+ { -- | A stack of 'HtmlTag's that represents a hierarchy of a currently+ -- parsing position in an 'HtmlTag' tree.+ tagStack :: HtmlTagStack+ , text :: Text+ }+ -- | Represent a token of an+ -- [HTML comment](https://www.w3.org/TR/html5/syntax.html#comments).+ | HtmlComment+ { -- | A stack of 'HtmlTag's that represents a hierarchy of a currently+ -- parsing position in an 'HtmlTag' tree.+ tagStack :: HtmlTagStack+ , comment :: Text+ }+ deriving (Eq, Ord, Show)
+ src/Text/Seonbi/Html/Preservation.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE NamedFieldPuns #-}+module Text.Seonbi.Html.Preservation+ ( isPreservedEntity+ , isPreservedTag+ , isPreservedTagStack+ ) where++import Prelude hiding (any)++import Text.Seonbi.Html.Entity+import Text.Seonbi.Html.Tag+import Text.Seonbi.Html.TagStack++-- | 'True' if the given tag should be preserved from transformation.+isPreservedTag :: HtmlTag -> Bool+isPreservedTag tag' =+ case tag' of+ Code -> True+ Kbd -> True+ Pre -> True+ TextArea -> True+ _ ->+ case htmlTagKind tag' of+ Normal -> False+ EscapableRawText -> False+ _ -> True++-- | 'True' if the given tag stack should be preserved from transformation.+isPreservedTagStack :: HtmlTagStack -> Bool+isPreservedTagStack = any isPreservedTag++-- | 'True' if the given HTML entity should be preserved from transformation.+isPreservedEntity :: HtmlEntity -> Bool+isPreservedEntity HtmlComment {} =+ True+isPreservedEntity HtmlStartTag { tagStack, tag } =+ isPreservedTag tag || isPreservedTagStack tagStack+isPreservedEntity HtmlEndTag { tagStack, tag } =+ isPreservedTag tag || isPreservedTagStack tagStack+isPreservedEntity entity =+ isPreservedTagStack $ tagStack entity
+ src/Text/Seonbi/Html/Printer.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE OverloadedStrings #-}+module Text.Seonbi.Html.Printer+ ( printHtml+ , printXhtml+ ) where++import Data.Char+import Data.List++import qualified Data.Text+import Data.Text.Lazy++import Text.Seonbi.Html.Entity+import Text.Seonbi.Html.Tag++-- | Print the list of 'HtmlEntity' into a lazy 'Text'.+--+-- >>> :set -XOverloadedStrings+-- >>> import Text.Seonbi.Html.Scanner+-- >>> let Done "" tokens = scanHtml "<p>Hello,<br>\n<em>world</em>!</p>"+-- >>> printHtml tokens+-- "<p>Hello,<br>\n<em>world</em>!</p>"+printHtml :: [HtmlEntity] -> Text+printHtml = printHtml' False++-- | Similar to 'printHtml' except it renders void (self-closing) tags as+-- like @<br/>@ instead of @<br>@.+--+-- >>> :set -XOverloadedStrings+-- >>> import Text.Seonbi.Html.Scanner+-- >>> let Done "" tokens = scanHtml "<p>Hello,<br>\n<em>world</em>!</p>"+-- >>> printXhtml tokens+-- "<p>Hello,<br/>\n<em>world</em>!</p>"+--+-- Note that normal tags are not rendered as self-closed; only void tags+-- according to HTML specification are:+--+-- >>> let Done "" tokens' = scanHtml "<p></p><p><br></p>"+-- >>> printXhtml tokens'+-- "<p></p><p><br/></p>"+printXhtml :: [HtmlEntity] -> Text+printXhtml = printHtml' True++printHtml' :: Bool -> [HtmlEntity] -> Text+printHtml' xhtml =+ Data.Text.Lazy.concat . Prelude.concatMap render . Data.List.groupBy isVoid+ where+ isVoid :: HtmlEntity -> HtmlEntity -> Bool+ isVoid (HtmlStartTag stck tg _) (HtmlEndTag stck' tg') =+ htmlTagKind tg == Void && stck == stck' && tg == tg'+ isVoid _ _ = False+ render :: [HtmlEntity] -> [Text]+ render [a@HtmlStartTag { tag = t, rawAttributes = at }, b@HtmlEndTag {}] =+ if isVoid a b+ then+ [ "<"+ , fromStrict (htmlTagName t)+ , renderAttrs at+ , if xhtml then "/>" else ">"+ ]+ else e a ++ e b+ render entities = Prelude.concatMap e entities+ e :: HtmlEntity -> [Text]+ e HtmlStartTag { tag = t, rawAttributes = a } =+ ["<", fromStrict (htmlTagName t), renderAttrs a, ">"]+ e HtmlEndTag { tag = t } = ["</", fromStrict (htmlTagName t), ">"]+ e HtmlText { rawText = t } = [fromStrict t]+ e HtmlCdata { text = t } = ["<![CDATA[", fromStrict t, "]]>"]+ e HtmlComment { comment = c } = ["<!--", fromStrict c, "-->"]+ renderAttrs :: Data.Text.Text -> Text+ renderAttrs "" = ""+ renderAttrs attrs+ | isSpace (Data.Text.head attrs) = fromStrict attrs+ | otherwise = ' ' `cons` fromStrict attrs
+ src/Text/Seonbi/Html/Scanner.hs view
@@ -0,0 +1,177 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TupleSections #-}+module Text.Seonbi.Html.Scanner+ ( Result (..)+ , scanHtml+ ) where++import Data.Char+import Prelude hiding (takeWhile)++import Data.Attoparsec.Text.Lazy+import Data.Map.Strict+import qualified Data.Text+import qualified Data.Text.Lazy++import Text.Seonbi.Html.Entity+import Text.Seonbi.Html.Tag+import Text.Seonbi.Html.TagStack++htmlFragments :: Parser [HtmlEntity]+htmlFragments = do+ result <- option [] $ fragments Text.Seonbi.Html.TagStack.empty+ txt <- htmlText Text.Seonbi.Html.TagStack.empty+ endOfInput+ return $ case txt of+ HtmlText { rawText = "" } -> result+ _ -> result ++ [txt]++fragments :: HtmlTagStack -> Parser [HtmlEntity]+fragments tagStack' = do+ txt <- htmlText tagStack'+ (entities, nextStack) <- htmlEntity tagStack'+ nextChunk <- option [] $ fragments nextStack+ let chunks = entities ++ nextChunk+ return $ case txt of+ HtmlText { rawText = "" } -> chunks+ txt' -> txt' : chunks++htmlText :: HtmlTagStack -> Parser HtmlEntity+htmlText tagStack' = do+ texts <- many' textFragment+ return $ mkText $ Data.Text.concat texts+ where+ mkText :: Data.Text.Text -> HtmlEntity+ mkText txt = HtmlText { tagStack = tagStack', rawText = txt }++textFragment :: Parser Data.Text.Text+textFragment = choice+ [ takeWhile1 (/= '<')+ , do+ a <- char '<'+ b <- satisfy $ \ c ->+ not (c == '!' || c == '/' || isAsciiUpper c || isAsciiLower c)+ return $ Data.Text.pack [a, b]+ ]++htmlEntity :: HtmlTagStack -> Parser ([HtmlEntity], HtmlTagStack)+htmlEntity tagStack' = choice+ [ htmlComment tagStack'+ , cdata tagStack'+ , startTag tagStack'+ , endTag tagStack'+ -- fallback:+ , (, tagStack') . (: []) . HtmlText tagStack' . Data.Text.singleton+ <$> anyChar+ ]++-- https://www.w3.org/TR/html5/syntax.html#comments+htmlComment :: HtmlTagStack -> Parser ([HtmlEntity], HtmlTagStack)+htmlComment tagStack' = do+ _ <- string "<!--"+ contents <- many' $ choice+ [ takeWhile1 (/= '-')+ , do+ a <- char '-'+ b <- notChar '-'+ return $ Data.Text.pack [a, b]+ , do+ a <- string "--"+ b <- notChar '>'+ return $ Data.Text.snoc a b+ ]+ _ <- string "-->"+ return+ ( [ HtmlComment+ { tagStack = tagStack'+ , comment = Data.Text.concat contents+ }+ ]+ , tagStack'+ )++-- https://www.w3.org/TR/html5/syntax.html#cdata-sections+cdata :: HtmlTagStack -> Parser ([HtmlEntity], HtmlTagStack)+cdata tagStack' = do+ _ <- string "<![CDATA["+ contents <- many' $ choice+ [ takeWhile1 (/= ']')+ , do+ a <- char ']'+ b <- notChar ']'+ return $ Data.Text.pack [a, b]+ , do+ a <- string "]]"+ b <- notChar '>'+ return $ Data.Text.snoc a b+ ]+ _ <- string "]]>"+ return+ ( [HtmlCdata { tagStack = tagStack', text = Data.Text.concat contents }]+ , tagStack'+ )++-- https://www.w3.org/TR/html5/syntax.html#start-tags+startTag :: HtmlTagStack -> Parser ([HtmlEntity], HtmlTagStack)+startTag tagStack' = do+ _ <- char '<'+ tag' <- htmlTag+ attributes <- many' $ choice+ [ do+ s <- char '"'+ c <- takeWhile (/= '"')+ e <- char '"'+ return (Data.Text.cons s $ Data.Text.snoc c e)+ , do+ s <- char '\''+ c <- takeWhile (/= '\'')+ e <- char '\''+ return (Data.Text.cons s $ Data.Text.snoc c e)+ , takeWhile1 $ \ c -> c /= '"' && c /= '\'' && c /= '/' && c /= '>'+ ]+ selfClosing <- option ' ' $ char '/'+ _ <- char '>'+ let (trailingEntities, nextTagStack) =+ if selfClosing == '/' || htmlTagKind tag' == Void+ then ([HtmlEndTag { tagStack = tagStack', tag = tag' }], tagStack')+ else ([], push tag' tagStack')+ return+ ( HtmlStartTag+ { tagStack = tagStack'+ , tag = tag'+ , rawAttributes = Data.Text.concat attributes+ } : trailingEntities+ , nextTagStack+ )++-- https://www.w3.org/TR/html5/syntax.html#end-tags+endTag :: HtmlTagStack -> Parser ([HtmlEntity], HtmlTagStack)+endTag tagStack' = do+ _ <- string "</"+ tag' <- htmlTag+ _ <- char '>'+ return $ case htmlTagKind tag' of+ Void -> ([], tagStack')+ _ ->+ let+ nextTagStack = pop tag' tagStack'+ in+ ( [HtmlEndTag { tagStack = nextTagStack, tag = tag' }]+ , nextTagStack+ )++htmlTag :: Parser HtmlTag+htmlTag = do+ name <- tagName+ case Data.Map.Strict.lookup (Data.Text.toLower name) htmlTagNames of+ Just t -> return t+ _ -> fail ("failed to parse; invalid tag: " ++ Data.Text.unpack name)++tagName :: Parser Data.Text.Text+tagName = do+ first <- satisfy $ \ c -> isAsciiUpper c || isAsciiLower c+ rest <- takeWhile $ \ c -> isAsciiUpper c || isAsciiLower c || isDigit c+ return $ Data.Text.cons first rest++scanHtml :: Data.Text.Lazy.Text -> Result [HtmlEntity]+scanHtml = parse htmlFragments
+ src/Text/Seonbi/Html/Tag.hs view
@@ -0,0 +1,327 @@+{-# LANGUAGE LambdaCase #-}+module Text.Seonbi.Html.Tag+ ( HtmlTag (..)+ , HtmlTagKind (..)+ , htmlTagKind+ , htmlTagName+ , htmlTagNames+ , htmlTags+ ) where++import Data.Map.Strict+import Data.Set+import Data.Text++-- $setup+-- >>> import Control.Applicative+-- >>> import Test.QuickCheck+-- >>> import Test.QuickCheck.Gen+-- >>> :{+-- instance Arbitrary HtmlTag where+-- arbitrary = elements $ Data.Set.toList htmlTags+-- :}++-- | The six [kinds of HTML elements+-- ](https://www.w3.org/TR/html5/syntax.html#writing-html-documents-elements).+data HtmlTagKind+ = Void+ | Template'+ | RawText+ | EscapableRawText+ | Foreign+ | Normal+ deriving (Eq, Ord, Show)++-- | HTML tags. This enumeration type contains both HTML 5 and 4 tags for+-- maximum compatibility.+data HtmlTag+ -- CHECK: When a new tag is added, add it into the list of htmlTags (see+ -- below).+ = A+ | Abbr+ | Acronym+ | Address+ | Area+ | Article+ | Aside+ | Audio+ | B+ | Base+ | Bdi+ | Bdo+ | Big+ | BlockQuote+ | Body+ | BR+ | Button+ | Canvas+ | Caption+ | Cite+ | Code+ | Col+ | ColGroup+ | Data+ | DataList+ | DD+ | Del+ | Details+ | Dfn+ | Dialog+ | Div+ | DL+ | DT+ | Em+ | Embed+ | FieldSet+ | FigCaption+ | Figure+ | Footer+ | Form+ | H1+ | H2+ | H3+ | H4+ | H5+ | H6+ | Head+ | Header+ | HR+ | Html+ | I+ | IFrame+ | Img+ | Input+ | Ins+ | Kbd+ | Label+ | Legend+ | LI+ | Link+ | Main+ | Map+ | Mark+ | Meta+ | Meter+ | Nav+ | NoScript+ | Object+ | OL+ | OptGroup+ | Option+ | Output+ | P+ | Param+ | Picture+ | Pre+ | Progress+ | Q+ | RB+ | RP+ | RT+ | RTC+ | Ruby+ | S+ | Samp+ | Script+ | Select+ | Section+ | Small+ | Source+ | Span+ | Strong+ | Style+ | Sub+ | Summary+ | Sup+ | Table+ | TBody+ | TD+ | Template+ | TFoot+ | TextArea+ | TH+ | THead+ | Time+ | Title+ | TR+ | Track+ | TT+ | U+ | UL+ | Var+ | Video+ | WBR+ deriving (Eq, Ord, Show)++-- | List all supported HTML tags.+--+-- >>> htmlTags+-- fromList [A,Abbr,Acronym,Address,...,UL,Var,Video,WBR]+htmlTags :: Set HtmlTag+htmlTags = Data.Set.fromList+ [ A, Abbr, Acronym, Address, Area, Article, Aside, Audio+ , B, Base, Bdi, Bdo, Big, BlockQuote, Body, BR, Button+ , Canvas, Caption, Cite, Code, Col, ColGroup+ , Data, DataList, DD, Del, Details, Dfn, Dialog, Div, DL, DT+ , Em, Embed+ , FieldSet, FigCaption, Figure, Footer, Form+ , H1, H2, H3, H4, H5, H6, Head, Header, HR, Html+ , I, IFrame, Img, Input, Ins+ , Kbd+ , Label, Legend, LI, Link+ , Main, Map, Mark, Meta, Meter+ , Nav, NoScript+ , Object, OL, OptGroup, Option, Output+ , P, Param, Picture, Pre, Progress+ , Q+ , RB, RP, RT, RTC, Ruby+ , S, Samp, Script, Select, Section, Small, Source+ , Span, Strong, Style, Sub, Summary, Sup+ , Table, TBody, TD, Template, TFoot, TextArea+ , TH, THead, Time, Title, TR, Track, TT+ , U, UL+ , Var, Video+ , WBR+ ]++-- | The name of an 'HtmlTag' in lowercase.+--+-- >>> htmlTagName TextArea+-- "textarea"+--+-- prop> \ t -> htmlTagName t == (toLower $ pack $ show (t :: HtmlTag))+htmlTagName :: HtmlTag -> Text+htmlTagName = toLower . pack . show++-- | The map of tag names to 'HtmlTag' values.+--+-- >>> :set -XOverloadedStrings+-- >>> Data.Map.Strict.lookup "blockquote" htmlTagNames+-- Just BlockQuote+--+-- prop> \ t -> Data.Map.Strict.lookup (htmlTagName t) htmlTagNames == Just t+htmlTagNames :: Map Text HtmlTag+htmlTagNames =+ Data.Map.Strict.fromList+ [(htmlTagName t, t) | t <- Data.Set.toList htmlTags]++-- | The kind of an 'HtmlTag'.+-- +-- >>> Data.Set.filter ((== EscapableRawText) . htmlTagKind) htmlTags+-- fromList [TextArea,Title]+htmlTagKind :: HtmlTag -> HtmlTagKind+htmlTagKind = \ case+ A -> Normal+ Abbr -> Normal+ Acronym -> Normal+ Address -> Normal+ Area -> Void+ Article -> Normal+ Aside -> Normal+ Audio -> Normal+ B -> Normal+ Base -> Void+ Bdi -> Normal+ Bdo -> Normal+ Big -> Normal+ BlockQuote -> Normal+ Body -> Normal+ BR -> Void+ Button -> Normal+ Canvas -> Foreign+ Caption -> Normal+ Cite -> Normal+ Code -> Normal+ Col -> Void+ ColGroup -> Normal+ Data -> Normal+ DataList -> Normal+ DD -> Normal+ Del -> Normal+ Details -> Normal+ Dfn -> Normal+ Dialog -> Normal+ Div -> Normal+ DL -> Normal+ DT -> Normal+ Em -> Normal+ Embed -> Void+ FieldSet -> Normal+ FigCaption -> Normal+ Figure -> Normal+ Footer -> Normal+ Form -> Normal+ H1 -> Normal+ H2 -> Normal+ H3 -> Normal+ H4 -> Normal+ H5 -> Normal+ H6 -> Normal+ Head -> Normal+ Header -> Normal+ HR -> Void+ Html -> Normal+ I -> Normal+ IFrame -> Normal+ Img -> Void+ Input -> Void+ Ins -> Normal+ Kbd -> Normal+ Label -> Normal+ Legend -> Normal+ LI -> Normal+ Link -> Void+ Main -> Normal+ Map -> Normal+ Mark -> Normal+ Meta -> Void+ Meter -> Normal+ Nav -> Normal+ NoScript -> Normal+ Object -> Normal+ OL -> Normal+ OptGroup -> Normal+ Option -> Normal+ Output -> Normal+ P -> Normal+ Param -> Void+ Picture -> Normal+ Pre -> Normal+ Progress -> Normal+ Q -> Normal+ RB -> Normal+ RP -> Normal+ RT -> Normal+ RTC -> Normal+ Ruby -> Normal+ S -> Normal+ Samp -> Normal+ Script -> RawText+ Select -> Normal+ Section -> Normal+ Small -> Normal+ Source -> Void+ Span -> Normal+ Strong -> Normal+ Style -> RawText+ Sub -> Normal+ Summary -> Normal+ Sup -> Normal+ Table -> Normal+ TBody -> Normal+ TD -> Normal+ Template -> Template'+ TFoot -> Normal+ TextArea -> EscapableRawText+ TH -> Normal+ THead -> Normal+ Time -> Normal+ Title -> EscapableRawText+ TR -> Normal+ Track -> Void+ TT -> Normal+ U -> Normal+ UL -> Normal+ Var -> Normal+ Video -> Normal+ WBR -> Void
+ src/Text/Seonbi/Html/TagStack.hs view
@@ -0,0 +1,146 @@+{-# LANGUAGE TypeFamilies #-}+module Text.Seonbi.Html.TagStack+ ( HtmlTagStack+ , Text.Seonbi.Html.TagStack.any+ , descendsFrom+ , Text.Seonbi.Html.TagStack.elem+ , depth+ , empty+ , fromList+ , pop+ , push+ , rebase+ , toList+ ) where++import Data.List+import GHC.Exts (IsList (..))++import Text.Seonbi.Html.Tag++-- | Represents a hierarchy of a currently parsing position in an 'HtmlTag'+-- tree.+--+-- For example, if an 'scanHtml' has read "@\<a href="#">\<b>\<i>foo\</i> bar@"+-- it is represented as @'HtmlTagStack' ['B', 'A']@.+--+-- Note that the tags are stored in reverse order, from the deepest to+-- the shallowest, to make inserting a more deeper tag efficient.+newtype HtmlTagStack = HtmlTagStack [HtmlTag] deriving (Eq, Ord)++instance IsList HtmlTagStack where+ type Item HtmlTagStack = HtmlTag+ fromList = HtmlTagStack . reverse+ toList (HtmlTagStack tags) = reverse tags++instance Show HtmlTagStack where+ show tags = "fromList " ++ show (toList tags)++-- | An empty stack.+empty :: HtmlTagStack+empty = HtmlTagStack []++-- | Count the depth of a stack.+--+-- >>> :set -XOverloadedLists+-- >>> depth empty+-- 0+-- >>> depth [Div, Article, P, Em]+-- 4+depth :: HtmlTagStack -> Int+depth (HtmlTagStack stack) = Data.List.length stack++-- | Build a new stack from a stack by replacing its bottom with a new base.+--+-- >>> :set -XOverloadedLists+-- >>> rebase [Article, BlockQuote] [Div] [Article, BlockQuote, P, Em]+-- fromList [Div,P,Em]+--+-- If there are no such bottom elements, it replaces nothing.+--+-- >>> rebase [Div, Article, BlockQuote] [Div] [Article, BlockQuote, P, Em]+-- fromList [Article,BlockQuote,P,Em]+rebase :: HtmlTagStack -> HtmlTagStack -> HtmlTagStack -> HtmlTagStack+rebase (HtmlTagStack base) (HtmlTagStack newBase) stack@(HtmlTagStack l)+ | base `isSuffixOf` l = HtmlTagStack $+ take (depth stack - length base) l ++ newBase+ | otherwise = stack++-- | Push one deeper @tag@ to a 'HtmlTagStack'.+--+-- >>> push A empty+-- fromList [A]+-- >>> push B (push A empty)+-- fromList [A,B]+push :: HtmlTag -> HtmlTagStack -> HtmlTagStack+push tag (HtmlTagStack tags) =+ HtmlTagStack (tag : tags)++-- | Pop the deepest @tag@ from a 'HtmlTagStack'.+--+-- >>> :set -XOverloadedLists+-- >>> pop Em [A, B, Em]+-- fromList [A,B]+--+-- It may pop a @tag@ in the middle if a @tag@ looking for is not the deepest:+--+-- >>> pop B [A, B, Em]+-- fromList [A,Em]+--+-- It does not affect to the input if there is no such @tag@ in the input:+--+-- >>> pop P [A, B, Em]+-- fromList [A,B,Em]+-- >>> pop A empty+-- fromList []+pop :: HtmlTag -> HtmlTagStack -> HtmlTagStack+pop tag (HtmlTagStack tags'@(t : ags)) =+ if t == tag+ then HtmlTagStack ags+ else+ let+ (head', rest) = span (/= tag) tags'+ tail' = case uncons rest of+ Just (_, tail'') -> tail''+ Nothing -> []+ in+ HtmlTagStack (head' ++ tail')+pop _ (HtmlTagStack []) = empty++-- | Check if a node ('HtmlEntity') that a 'HtmlTagStack' (the first argument) +-- refers is contained by a node that another 'HtmlTagStack' (the second+-- argument), or they are sibling at least.+--+-- >>> :set -XOverloadedLists+-- >>> descendsFrom [Div, P, A, Em] [Div, P, A]+-- True+-- >>> descendsFrom [Div, P, A] [Div, P, A]+-- True+-- >>> descendsFrom [Div, P, Em] [Div, P, A]+-- False+-- >>> descendsFrom [Div, P] [Div, P, A]+-- False+descendsFrom :: HtmlTagStack -> HtmlTagStack -> Bool+HtmlTagStack a `descendsFrom` HtmlTagStack b =+ b `isSuffixOf` a++-- | Determine whether any element of the tag stack satisfies the predicate.+--+-- >>> :set -XOverloadedLists+-- >>> Text.Seonbi.Html.TagStack.any ((== Void) . htmlTagKind) [Div, P, Script]+-- False+-- >>> Text.Seonbi.Html.TagStack.any ((== Void) . htmlTagKind) [BR, P, Script]+-- True+any :: (HtmlTag -> Bool) -> HtmlTagStack -> Bool+any fn (HtmlTagStack stack) =+ Prelude.any fn stack++-- | Determine whether the element occurs in the tag stack.+--+-- >>> :set -XOverloadedLists+-- >>> A `Text.Seonbi.Html.TagStack.elem` [A, B, Code]+-- True+-- >>> Em `Text.Seonbi.Html.TagStack.elem` [A, B, Code]+-- False+elem :: HtmlTag -> HtmlTagStack -> Bool+elem tag (HtmlTagStack stack) = tag `Prelude.elem` stack
+ src/Text/Seonbi/Html/TextNormalizer.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+module Text.Seonbi.Html.TextNormalizer+ ( escapeHtmlEntities+ , normalizeCdata+ , normalizeText+ ) where++import Control.Exception+import Data.List++import Data.Text hiding (groupBy, map)++import Text.Seonbi.Html.Entity++-- | As 'scanHtml' may emit two or more continuous 'HtmlText' fragments even+-- if these can be represented as only one 'HtmlText' fragment, it makes+-- postprocessing hard.+--+-- The 'normalizeText' function concatenates such continuous 'HtmlText'+-- fragments into one if possible so that postprocessing can be easy:+--+-- >>> :set -XOverloadedStrings -XOverloadedLists+-- >>> normalizeText [HtmlText [] "Hello, ", HtmlText [] "world!"]+-- [HtmlText {tagStack = fromList [], rawText = "Hello, world!"}]+--+-- It also transforms all 'HtmlCdata' fragments into an 'HtmlText' together.+--+-- >>> :{+-- normalizeText [ HtmlText [] "foo "+-- , HtmlCdata [] "<bar>", HtmlText [] " baz!"+-- ]+-- :}+-- [HtmlText {tagStack = fromList [], rawText = "foo <bar> baz!"}]+normalizeText :: [HtmlEntity] -> [HtmlEntity]+normalizeText fragments =+ [ case map normalizeCdata frags of+ [f] ->+ f+ frags'@(HtmlText { tagStack = s }:_) ->+ HtmlText+ { tagStack = s+ , rawText = Data.Text.concat $ map rawText frags'+ }+ frags' ->+ throw $ AssertionFailed+ ("Unexpected error occured; grouping does not work well: " +++ show frags')+ | frags <- groupBy isSibling fragments+ ]+ where+ isSibling :: HtmlEntity -> HtmlEntity -> Bool+ isSibling HtmlText { tagStack = a } HtmlText { tagStack = b } = a == b+ isSibling HtmlText { tagStack = a } HtmlCdata { tagStack = b } = a == b+ isSibling HtmlCdata { tagStack = a } HtmlText { tagStack = b } = a == b+ isSibling HtmlCdata { tagStack = a } HtmlCdata { tagStack = b } = a == b+ isSibling _ _ = False++-- | Transform a given 'HtmlCdata' node into an equivalent 'HtmlText' node.+--+-- >>> import Text.Seonbi.Html.Tag+-- >>> normalizeCdata HtmlCdata { tagStack = [P], text = "<p id=\"foo\">" }+-- HtmlText {tagStack = fromList [P], rawText = "<p id="foo">"}+normalizeCdata :: HtmlEntity -> HtmlEntity+normalizeCdata HtmlCdata { tagStack = s, text = t } =+ HtmlText { tagStack = s, rawText = escapeHtmlEntities t }+normalizeCdata entity = entity++-- | Escape special (control) characters into corresponding character entities+-- in the given HTML text.+--+-- >>> escapeHtmlEntities "<foo & \"bar\">"+-- "<foo & "bar">"+escapeHtmlEntities :: Text -> Text+escapeHtmlEntities =+ Data.Text.concatMap $ \ case+ '<' -> "<"+ '>' -> ">"+ '&' -> "&"+ '"' -> """+ c -> Data.Text.singleton c
+ src/Text/Seonbi/Html/Wrapper.hs view
@@ -0,0 +1,64 @@+module Text.Seonbi.Html.Wrapper+ ( isWrappedBy+ , isWrappedBy'+ , wrap+ ) where++import Text.Seonbi.Html+import Text.Seonbi.Html.TagStack++-- | Wraps given entities with an element.+wrap :: HtmlTagStack -> HtmlTag -> HtmlRawAttrs -> [HtmlEntity] -> [HtmlEntity]+wrap baseStack tag' attributes entities = (:)+ (HtmlStartTag baseStack tag' attributes)+ [ e { tagStack = rebase' (tagStack e) }+ | e <- entities+ ] ++ [HtmlEndTag baseStack tag']+ where+ newBaseStack :: HtmlTagStack+ newBaseStack = push tag' baseStack+ rebase' :: HtmlTagStack -> HtmlTagStack+ rebase' = rebase baseStack newBaseStack++-- | A shortcut to 'isWrappedBy'' of wildcard attributes match.+isWrappedBy :: [HtmlEntity] -> HtmlTag -> Bool+isWrappedBy entities tag' =+ isWrappedBy' entities tag' Nothing++-- | 'True' if the given @['HtmlEntity']@ is wrapped by a tag and attributes.+-- E.g.:+--+-- >>> :set -XOverloadedLists+-- >>> :set -XOverloadedStrings+-- >>> :{+-- let entities = +-- [ HtmlStartTag [] Em " id=foo"+-- , HtmlText [Em] "Hello"+-- , HtmlEndTag [] Em+-- ] :: [HtmlEntity]+-- :}+--+-- >>> isWrappedBy' entities Em $ Just " id=foo"+-- True+-- >>> isWrappedBy' entities Div $ Just " id=foo"+-- False+-- >>> isWrappedBy' entities Em $ Just " id=wrong"+-- False+--+-- In order to match to any attributes (wildcard match), give 'Nothing' to+-- the third argument:+--+-- >>> isWrappedBy' entities Em Nothing+-- True+-- >>> isWrappedBy' entities Span Nothing+-- False+--+-- Or you can use 'isWrappedBy' function which is a shortcut for that.+isWrappedBy' :: [HtmlEntity] -> HtmlTag -> Maybe HtmlRawAttrs -> Bool+isWrappedBy' entities@(HtmlStartTag s t a : _) tag' attributes =+ case Prelude.last entities of+ HtmlEndTag s' t' ->+ t == tag' && t' == tag' && s == s' && maybe True (== a) attributes+ _ ->+ False+isWrappedBy' _ _ _ = False
+ src/Text/Seonbi/PairedTransformer.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE ScopedTypeVariables #-}+module Text.Seonbi.PairedTransformer+ ( PairedTransformer (..)+ , transformPairs+ ) where++import Data.Text hiding (break, reverse)++import Text.Seonbi.Html++-- | Settings for 'transformPairs'.+data PairedTransformer match = PairedTransformer+ { ignoresTagStack :: HtmlTagStack -> Bool+ , matchStart :: [match] -> Text -> Maybe (match, Text, Text, Text)+ , matchEnd :: Text -> Maybe (match, Text, Text, Text)+ , areMatchesPaired :: match -> match -> Bool+ , transformPair :: match -> match -> [HtmlEntity] -> [HtmlEntity]+ }++-- | Some transformations should be done only if a start and an end are paired+-- like parentheses. These even usually can be nested. Even if there is+-- a start and an end they should not be paired unless they are sibling in+-- an HTML tree.+--+-- These kinds of scanning are easily turned highly stateful and imperative,+-- hence hard to debug. This base class provides the common logic between+-- these kinds of paired transformations so that an implementation class fill+-- several abstract methods triggered by the state machine.+transformPairs :: forall m . PairedTransformer m -> [HtmlEntity] -> [HtmlEntity]+transformPairs (PairedTransformer ignores start end arePaired transform) =+ iter [] . normalizeText+ where+ iter :: [Unclosed m] -> [HtmlEntity] -> [HtmlEntity]+ iter [] [] = []+ iter stack [] = unstack stack+ iter stack (x@HtmlText { tagStack = ts, rawText = txt } : xs) =+ case (startMatch, endMatch) of+ (Just captured, Nothing) ->+ roll stack captured ts xs+ (Nothing, Just captured@(m, _, _, _))+ | Prelude.any ((`arePaired` m) . match) stack ->+ unroll stack captured ts xs+ (Just captured@(_, pre, _, _), Just captured'@(m', pre', _, _)) ->+ if Data.Text.length pre >= Data.Text.length pre' &&+ Prelude.any ((`arePaired` m') . match) stack+ then unroll stack captured' ts xs+ else roll stack captured ts xs+ (Nothing, _) ->+ case stack of+ [] -> x : iter stack xs+ s : ss -> iter (s { buffer = x : buffer s } : ss) xs+ where+ startMatch :: Maybe (m, Text, Text, Text)+ startMatch = start (reverse $ fmap match stack) txt+ endMatch :: Maybe (m, Text, Text, Text)+ endMatch = end txt+ iter (s@Unclosed {} : ss) (x : xs) =+ iter (s { buffer = x : buffer s } : ss) xs+ iter [] (x : xs) = x : iter [] xs+ roll :: [Unclosed m]+ -> (m, Text, Text, Text)+ -> HtmlTagStack+ -> [HtmlEntity]+ -> [HtmlEntity]+ roll [] (startMatch, pre, t, post) tagStack_ entities =+ prependText tagStack_ pre $ iter+ [Unclosed startMatch [HtmlText tagStack_ t]]+ (normalizeText (prependText tagStack_ post entities))+ roll (s : ss) (startMatch, pre, t, post) tagStack_ entities = iter+ ( Unclosed startMatch [HtmlText tagStack_ t]+ : s { buffer = prependText tagStack_ pre $ buffer s }+ : ss+ )+ (normalizeText (prependText tagStack_ post entities))+ unroll :: [Unclosed m]+ -> (m, Text, Text, Text)+ -> HtmlTagStack+ -> [HtmlEntity]+ -> [HtmlEntity]+ unroll stack (endMatch, pre, t, post) tagStack_ es =+ case remainStack of+ [] -> unrolled ++ iter [] remainEntities+ s : ss -> iter+ (s { buffer = reverse unrolled ++ buffer s } : ss)+ remainEntities+ where+ prependText' :: Text -> [HtmlEntity] -> [HtmlEntity]+ prependText' = prependText tagStack_+ unrolled :: [HtmlEntity]+ remainStack :: [Unclosed m]+ (unrolled, remainStack) = case findPair endMatch stack of+ (_, []) ->+ ([HtmlText tagStack_ (pre `append` t)], [])+ (stack', s@Unclosed { match = startMatch } : ss) ->+ let+ buf = prependText' pre (unstack' stack' ++ buffer s)+ buf' = prependText' t buf+ buf'' = reverse buf'+ transformed = if Prelude.any (ignores . tagStack) buf''+ then buf''+ else transform startMatch endMatch buf''+ in+ (transformed, ss)+ remainEntities :: [HtmlEntity]+ remainEntities = prependText' post es+ findPair :: m -> [Unclosed m] -> ([Unclosed m], [Unclosed m])+ findPair m = break (arePaired m . match)+ unstack :: [Unclosed m] -> [HtmlEntity]+ unstack = reverse . unstack'+ unstack' :: [Unclosed m] -> [HtmlEntity]+ unstack' [] = []+ unstack' (Unclosed { buffer = b } : ss) = b ++ unstack' ss+ prependText :: HtmlTagStack -> Text -> [HtmlEntity] -> [HtmlEntity]+ prependText tagStack_ txt+ | Data.Text.null txt = id+ | otherwise = (HtmlText tagStack_ txt :)++data Unclosed match = Unclosed+ { match :: match+ , buffer :: [HtmlEntity] -- in reverse order+ }
+ src/Text/Seonbi/Punctuation.hs view
@@ -0,0 +1,632 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+module Text.Seonbi.Punctuation+ ( ArrowTransformationOption (..)+ , CitationQuotes (..)+ , Quotes (..)+ , QuotePair (..)+ , angleQuotes+ , cornerBrackets+ , curvedQuotes+ , curvedSingleQuotesWithQ+ , guillemets+ , quoteCitation+ , transformArrow+ , transformEllipsis+ , transformEmDash+ , transformQuote+ ) where++import Prelude hiding (takeWhile)++import Control.Monad+import Data.Char (isSpace)+import Data.Either+import Data.List (minimumBy)+import Data.Maybe+import Data.Ord++import Data.Attoparsec.Text+import Data.Set+import Data.Text hiding (any, length, takeWhile)+import qualified Data.Text++import Text.Seonbi.Html+import Text.Seonbi.Html.Clipper+import Text.Seonbi.Html.Preservation+import Text.Seonbi.Html.Wrapper+import Text.Seonbi.PairedTransformer++-- | A set of quoting parentheses to be used by 'quoteCitation' function.+--+-- There are two presets: 'angleQuotes' and 'cornerBrackets'. These both+-- surround titles with a @\<cite>@ tag. In order to disable surrounded+-- elements, set 'htmlElement' field to 'Nothing', e.g.:+--+-- @+-- 'angleQuotes' { 'htmlElement' = 'Nothing' }+-- @+data CitationQuotes = CitationQuotes+ { -- | The leading and trailing punctuations to surround a title of+ -- novel, newspaper, magazine, movie, televison program, etc.+ title :: (Text, Text)+ , -- | The leading and trailing punctuations to surround a title of+ -- short story, chapter, article, episode, etc.+ subtitle :: (Text, Text)+ , -- | Optional pair of an HTML element and its attributes to surround+ -- citations. E.g., if it is @'Just' ('Cite', " class=\"autogen\")@+ -- titles are transformed like @\<cite class="autogen">이런 날\</cite>@.+ htmlElement :: Maybe (HtmlTag, HtmlRawAttrs)+ } deriving (Eq, Show)++-- | Cite a title using angle quotes, used by South Korean orthography in+-- horizontal writing (橫書), e.g., 《나비와 엉겅퀴》 or 〈枾崎의 바다〉.+angleQuotes :: CitationQuotes+angleQuotes = CitationQuotes+ { title = ("《", "》")+ , subtitle = ("〈", "〉")+ , htmlElement = Just (Cite, "")+ }++-- | Cite a title using corner brackets, used by South Korean orthography in+-- vertical writing (縱書) and Japanese orthography,+-- e.g., 『나비와 엉겅퀴』 or 「枾崎의 바다」.+cornerBrackets :: CitationQuotes+cornerBrackets = CitationQuotes+ { title = ("『", "』")+ , subtitle = ("「", "」")+ , htmlElement = Just (Cite, "")+ }++-- | People tend to cite the title of a work (e.g., a book, a paper, a poem,+-- a song, a film, a TV show, a game) by wrapping inequality symbols+-- like @\<\<나비와 엉겅퀴>>@ or @\<枾崎의 바다>@ instead of proper angle quotes+-- like @《나비와 엉겅퀴》@ or @〈枾崎의 바다〉@.+--+-- This transforms, in the given HTML fragments, all folk-citing quotes into+-- typographic citing quotes:+--+-- - Pairs of less-than and greater-than inequality symbols (@<@ & @>@) into+-- pairs of proper angle quotes (@〈@ & @〉@)+-- - Pairs of two consecutive inequality symbols (@<<@ & @>>@) into+-- pairs of proper double angle quotes (@《@ & @》@)+quoteCitation :: CitationQuotes -- ^ Quoting parentheses to wrap titles.+ -> [HtmlEntity] -- ^ The input HTML entities to transform.+ -> [HtmlEntity]+quoteCitation quotes =+ transformPairs pairedTransformer+ where+ pairedTransformer :: PairedTransformer TitlePunct+ pairedTransformer = PairedTransformer+ { ignoresTagStack = isPreservedTagStack+ , matchStart = \ _ -> matcher $ parser openTitle openSubtitle+ , matchEnd = matcher $ parser closeTitle closeSubtitle+ , areMatchesPaired = (==)+ , transformPair = transformPair'+ }+ transformPair' :: TitlePunct -> TitlePunct -> [HtmlEntity] -> [HtmlEntity]+ transformPair' punct _ buffer =+ case cited of+ [] -> []+ entities@(x : _) ->+ let+ ts = tagStack x+ makeText = HtmlText ts+ category = case punct of+ DoubleAngle -> title+ DoubleCorner -> title+ DoubleInequal -> title+ Angle -> subtitle+ Corner -> subtitle+ Inequal -> subtitle+ (startP, endP) = category quotes+ in+ makeText startP : entities ++ [makeText endP]+ where+ buffer' :: [HtmlEntity]+ buffer' = Prelude.drop 1 $ Prelude.take (length buffer - 1) buffer+ cited :: [HtmlEntity]+ cited = case (htmlElement quotes, buffer') of+ (Nothing, b) -> b+ (_, []) -> []+ (Just (tag', ""), x : _) ->+ if buffer' `isWrappedBy` tag'+ then buffer'+ else wrap (tagStack x) tag' "" buffer'+ (Just (tag', attrs), x : _) ->+ if isWrappedBy' buffer' tag' (Just attrs)+ then buffer'+ else wrap (tagStack x) tag' attrs buffer'+ specialChars :: Set Char+ specialChars =+ [ '<', '>', '&'+ , '\x3008', '\x3009', '\x300a', '\x300b', '\x300e', '\x300f'+ ]+ matcher :: Parser [Either Text (TitlePunct, Text, Text)]+ -> Text+ -> Maybe (TitlePunct, Text, Text, Text)+ matcher parser' text' = case parseOnly parser' text' of+ Left _ -> Nothing+ Right matches -> case partitionEithers matches of+ (l, [(punct, m, post)]) -> Just (punct, Data.Text.concat l, m, post)+ _ -> Nothing+ parser :: Parser (TitlePunct, Text)+ -> Parser (TitlePunct, Text)+ -> Parser [Either Text (TitlePunct, Text, Text)]+ parser title' subtitle' = many' $ choice+ [ Left <$> takeWhile1 (`notElem` specialChars)+ , do+ (punct, m) <- title'+ remain <- takeWhile (const True)+ return $ Right (punct, m, remain)+ , do+ (punct, m) <- subtitle'+ remain <- takeWhile (const True)+ return $ Right (punct, m, remain)+ , Left . Data.Text.singleton <$> anyChar+ ]+ openTitle :: Parser (TitlePunct, Text)+ openTitle = choice+ [ leftDoubleAngle+ , leftDoubleCorner+ , (DoubleInequal,) <$> double' lt+ ]+ closeTitle :: Parser (TitlePunct, Text)+ closeTitle = choice+ [ rightDoubleAngle+ , rightDoubleCorner+ , (DoubleInequal,) <$> double' gt+ ]+ double' :: Parser Text -> Parser Text+ double' p = do+ t <- p+ t' <- p+ return (t `append` t')+ openSubtitle :: Parser (TitlePunct, Text)+ openSubtitle = choice [leftAngle, (Inequal,) <$> lt]+ closeSubtitle :: Parser (TitlePunct, Text)+ closeSubtitle = choice [rightAngle, (Inequal,) <$> gt]+ leftAngle :: Parser (TitlePunct, Text)+ leftAngle = (Angle,) <$> choice+ [ Data.Text.singleton <$> char '\x3008'+ , string "〈"+ , asciiCI "〈"+ ]+ rightAngle :: Parser (TitlePunct, Text)+ rightAngle = (Angle,) <$> choice+ [ Data.Text.singleton <$> char '\x3009'+ , string "〉"+ , asciiCI "〉"+ ]+ leftDoubleAngle :: Parser (TitlePunct, Text)+ leftDoubleAngle = (DoubleAngle,) <$> choice+ [ Data.Text.singleton <$> char '\x300a'+ , string "《"+ , asciiCI "《"+ ]+ rightDoubleAngle :: Parser (TitlePunct, Text)+ rightDoubleAngle = (DoubleAngle,) <$> choice+ [ Data.Text.singleton <$> char '\x300b'+ , string "》"+ , asciiCI "》"+ ]+ leftDoubleCorner :: Parser (TitlePunct, Text)+ leftDoubleCorner = (DoubleCorner,) <$> choice+ [ Data.Text.singleton <$> char '\x300e'+ , string "『"+ , asciiCI "『"+ ]+ rightDoubleCorner :: Parser (TitlePunct, Text)+ rightDoubleCorner = (DoubleCorner,) <$> choice+ [ Data.Text.singleton <$> char '\x300f'+ , string "』"+ , asciiCI "』"+ ]++data TitlePunct+ = DoubleAngle | Angle+ | DoubleCorner | Corner+ | DoubleInequal | Inequal+ deriving (Eq, Show)+++-- | Substitution options for 'transformArrow' function. These options can+-- be composited as an element of a set.+--+-- - @[]@: Transform only leftwards and rightwards arrows.+-- - @['LeftRight']@: Transform bi-directional arrows as well as left/rightwards+-- arrows.+-- - @['DoubleArrow']@: Transform double arrows as well as single arrows.+-- - @['LeftRight', 'DoubleArrow']@: Transform all types of arrows.+data ArrowTransformationOption+ -- | A bidirect arrow (e.g., ↔︎).+ = LeftRight+ -- | An arrow which has two lines (e.g., ⇒).+ | DoubleArrow+ deriving (Eq, Ord, Show)++-- | Transforms hyphens and less-than and greater-than inequality symbols that+-- mimic arrows into actual arrow characters:+--+-- - @->@ turns into @→@ (U+2192 RIGHTWARDS ARROW).+-- - @<-@ turns into @←@ (U+2190 LEFTWARDS ARROW).+-- - @\<->@ turns into @↔@ (U+2194 LEFT RIGHT ARROW)+-- if 'LeftRight' is configured.+-- - @=>@ turns into @⇒@ (U+21D2 RIGHTWARDS DOUBLE ARROW)+-- if 'DoubleArrow' is configured.+-- - @<=@ turns into @⇐@ (U+21D0 LEFTWARDS DOUBLE ARROW)+-- if 'DoubleArrow' is configured.+-- - @\<=>@ turns into @⇔@ (U+21D4 LEFT RIGHT DOUBLE ARROW)+-- if both 'DoubleArrow' and 'LeftRight' are configured at a time.+transformArrow :: Set ArrowTransformationOption -> [HtmlEntity] -> [HtmlEntity]+transformArrow options input = (`fmap` normalizeText input) $ \ case+ e@HtmlText { tagStack = stack, rawText = txt } ->+ if isPreservedTagStack stack+ then e+ else e { rawText = replaceText txt }+ e ->+ e+ where+ replaceText :: Text -> Text+ replaceText txt =+ case parseOnly parser txt of+ Left _ -> error "unexpected error: failed to parse text node"+ Right t -> t+ specialChars :: Set Char+ specialChars = if DoubleArrow `elem` options+ then ['<', '>', '&', '-', '=']+ else ['<', '>', '&', '-']+ parser :: Parser Text+ parser = do+ chunks <- many' $ choice+ [ takeWhile1 (`notElem` specialChars)+ , choice arrows+ , Data.Text.singleton <$> anyChar+ ]+ endOfInput+ return $ Data.Text.concat chunks+ arrows :: [Parser Text]+ arrows = catMaybes+ [ if DoubleArrow `elem` options && LeftRight `elem` options+ then Just doubleLeftRight+ else Nothing+ , if DoubleArrow `elem` options then Just doubleLeft else Nothing+ , if DoubleArrow `elem` options then Just doubleRight else Nothing+ , if LeftRight `elem` options then Just leftRight else Nothing+ , Just left+ , Just right+ ]+ doubleLeftRight :: Parser Text+ doubleLeftRight = lt >> equals >> gt >> return "⇔"+ doubleLeft :: Parser Text+ doubleLeft = lt >> equals >> return "⇐"+ doubleRight :: Parser Text+ doubleRight = equals >> gt >> return "⇒"+ leftRight :: Parser Text+ leftRight = lt >> hyphen >> gt >> return "↔"+ left :: Parser Text+ left = lt >> hyphen >> return "←"+ right :: Parser Text+ right = hyphen >> gt >> return "→"+ hyphen :: Parser ()+ hyphen = void $ choice+ [ char '-' >> return ""+ , string "‐"+ , string "‐"+ , string "-"+ , asciiCI "-"+ ]+ equals :: Parser ()+ equals = void $ choice+ [ char '=' >> return ""+ , string "="+ , string "&61;"+ , asciiCI "="+ ]++lt :: Parser Text+lt = choice+ [ Data.Text.singleton <$> char '<'+ , string "<"+ , string "<"+ , asciiCI "<"+ ]++gt :: Parser Text+gt = choice+ [ Data.Text.singleton <$> char '>'+ , string ">"+ , string ">"+ , asciiCI ">"+ ]++-- | Until 2015, the National Institute of Korean Language (國立國語院) had+-- allowed to use only ellipses (@…@) for omitted word, phrase, line,+-- paragraph, or speechlessness. However, people tend to use three or more+-- consecutive periods (@...@) instead of a proper ellipsis.+-- Although NIKL has started to allow consecutive periods besides an ellipsis+-- for these uses, ellipses are still a proper punctuation in principle.+--+-- This transforms, in the given HTML fragments, all three consecutive periods+-- into proper ellipses.+transformEllipsis :: [HtmlEntity] -> [HtmlEntity]+transformEllipsis = transformText $ \ txt ->+ case parseOnly parser txt of+ Left _ -> error "unexpected error: failed to parse text node"+ Right t -> t+ where+ parser :: Parser Text+ parser = do+ chunks <- many' $ choice+ [ takeWhile1 (`notElem` (['&', '.'] :: Set Char))+ , ellipsis+ , Data.Text.singleton <$> anyChar+ ]+ endOfInput+ return $ Data.Text.concat chunks+ ellipsis :: Parser Text+ ellipsis = do+ void $ period >> period >> period+ return "…"+ period :: Parser Text+ period = choice+ [ string "."+ , string "."+ , string "."+ , asciiCI "."+ ]++-- | Pairs of substitute folk single and double quotes.+-- Used by 'transformQuote' function.+--+-- The are three presets: 'curvedQuotes', 'guillemets', and+-- 'curvedSingleQuotesWithQ':+--+-- - 'curvedQuotes' uses South Korean curved quotation marks which follows+-- English quotes (@‘@: U+2018, @’@: U+2019, @“@: U+201C, @”@: U+201D)+-- - 'guillemets' uses North Korean angular quotation marks, influenced+-- by Russian guillemets but with some adjustments to replace guillemets with+-- East Asian angular quotes (@〈@: U+3008, @〉@: U+3009, @《@: U+300A,+-- @》@: U+300B).+-- - 'curvedSingleQuotesWithQ' is the almost same to 'curvedQuotes' but+-- wrap text with a @\<q>@ tag instead of curved double quotes.+data Quotes = Quotes+ { singleQuotes :: QuotePair+ , doubleQuotes :: QuotePair+ } deriving (Eq, Ord, Show)++-- | A pair of an opening quote and a closing quote.+data QuotePair+ -- | Wrap the quoted text with a pair of punctuation characters.+ = QuotePair Text Text+ -- | Wrap the quoted text (HTML elements) with an element like @\<q>@ tag.+ | HtmlElement HtmlTag HtmlRawAttrs+ deriving (Eq, Ord, Show)++-- | English-style curved quotes (@‘@: U+2018, @’@: U+2019, @“@: U+201C,+-- @”@: U+201D), which are used by South Korean orthography.+curvedQuotes :: Quotes+curvedQuotes = Quotes+ { singleQuotes = QuotePair "‘" "’"+ , doubleQuotes = QuotePair "“" "”"+ }++-- | East Asian guillemets (@〈@: U+3008, @〉@: U+3009, @《@: U+300A, @》@:+-- U+300B), which are used by North Korean orthography.+guillemets :: Quotes+guillemets = Quotes+ { singleQuotes = QuotePair "〈" "〉"+ , doubleQuotes = QuotePair "《" "》"+ }++-- | Use English-style curved quotes (@‘@: U+2018, @’@: U+2019) for single+-- quotes, and HTML @\<q\>@ tags for double quotes.+curvedSingleQuotesWithQ :: Quotes+curvedSingleQuotesWithQ = Quotes+ { singleQuotes = QuotePair "‘" "’"+ , doubleQuotes = HtmlElement Q ""+ }++-- | Transform pairs of apostrophes (@'@: U+0027) and straight double+-- quotes (@"@: U+0022) into more appropriate quotation marks like+-- typographic single quotes (@‘@: U+2018, @’@: U+2019) and+-- double quotes (@“@: U+201C, @”@: U+201D), or rather wrap them with an HTML+-- element like @\<q>@ tag. It depends on the options passed to the first+-- parameter; see also 'Quotes'.+transformQuote :: Quotes -- ^ Pair of quoting punctuations and wrapping element.+ -> [HtmlEntity] -- ^ The input HTML entities to transform.+ -> [HtmlEntity]+transformQuote Quotes { .. } = transformPairs $+ PairedTransformer+ { ignoresTagStack = isPreservedTagStack+ , matchStart = matchStart'+ , matchEnd = matchEnd'+ , areMatchesPaired = \ (punct, text) (punct', text') ->+ arePaired punct punct' && text == text'+ , transformPair = transformPair'+ }+ where+ punctuations :: [(QuotePunct, [Text])]+ punctuations =+ [ ( Apostrophe+ , ["'", "'", "'", "'", "'"]+ )+ , ( DoubleQuote+ , ["\"", """, """, """, """, """]+ )+ , ( DoubleQuote+ , ["\"", """, """, """, """, """]+ )+ , ( OpeningSingleQuote+ , [ "\x2018", "‘", "‘"+ , "‘", "‘", "‘"+ ]+ )+ , ( ClosingSingleQuote+ , [ "\x2019", "’", "’", "’"+ , "’", "’", "’"+ ]+ )+ , ( OpeningDoubleQuote+ , [ "\x201c", "“", "“"+ , "“", "“", "“", "“", "“"+ ]+ )+ , ( ClosingDoubleQuote+ , [ "\x201d", "”", "”", "”"+ , "”", "”", "”", "”", "”"+ ]+ )+ ]+ matchStart' :: [(QuotePunct, Text)]+ -> Text+ -> Maybe ((QuotePunct, Text), Text, Text, Text)+ matchStart' prevMatches text+ | Prelude.null prevMatcherCandidates = Nothing+ | otherwise =+ let (matcher, entity, (pre, post)) = minimumBy+ (comparing $ \ (_, _, (pre', _)) -> Data.Text.length pre')+ prevMatcherCandidates+ in+ if Data.Text.null post then+ Nothing+ else+ Just+ ( (matcher, entity)+ , pre+ , entity+ , Data.Text.drop (Data.Text.length entity) post+ )+ where+ prevMatchers :: Set QuotePunct+ prevMatchers = Data.Set.fromList (fst <$> prevMatches)+ prevMatcherCandidates :: [(QuotePunct, Text, (Text, Text))]+ prevMatcherCandidates =+ [ (matcher', entity', breakOn entity' text)+ | (matcher', entities) <- punctuations+ , opens matcher'+ , matcher' `Data.Set.notMember` prevMatchers+ , entity' <- entities+ ]+ matchEnd' :: Text -> Maybe ((QuotePunct, Text), Text, Text, Text)+ matchEnd' text+ | Prelude.null matcherCandidates = Nothing+ | otherwise =+ let (matcher, entity, (pre, post)) = minimumBy+ (comparing $ \ (_, _, (pre', _)) -> Data.Text.length pre')+ matcherCandidates+ in+ if Data.Text.null post then+ Nothing+ else+ Just+ ( (matcher, entity)+ , pre+ , entity+ , Data.Text.drop (Data.Text.length entity) post+ )+ where+ matcherCandidates :: [(QuotePunct, Text, (Text, Text))]+ matcherCandidates =+ [ (matcher', entity', breakOn entity' text)+ | (matcher', entities) <- punctuations+ , closes matcher'+ , entity' <- entities+ ]+ transformPair' :: (QuotePunct, Text)+ -> (QuotePunct, Text)+ -> [HtmlEntity]+ -> [HtmlEntity]+ transformPair' (punct, start) (_, end) buffer@(firstEntity : _) =+ case clipText start end buffer of+ Nothing -> buffer+ Just es -> case pair of+ QuotePair open close ->+ HtmlText tagStack' open : es ++ [HtmlText tagStack' close]+ HtmlElement tag attrs ->+ wrap tagStack' tag attrs es+ where+ pair :: QuotePair+ pair = case punct of+ DoubleQuote -> doubleQuotes+ OpeningDoubleQuote -> doubleQuotes+ ClosingDoubleQuote -> doubleQuotes+ _ -> singleQuotes+ tagStack' :: HtmlTagStack+ tagStack' = tagStack firstEntity+ transformPair' _ _ [] = []+ arePaired :: QuotePunct -> QuotePunct -> Bool+ arePaired OpeningSingleQuote = (== ClosingSingleQuote)+ arePaired OpeningDoubleQuote = (== ClosingDoubleQuote)+ arePaired punct = (== punct)++data QuotePunct+ = DoubleQuote+ | Apostrophe+ | OpeningSingleQuote | ClosingSingleQuote+ | OpeningDoubleQuote | ClosingDoubleQuote+ deriving (Eq, Ord, Show)++opens :: QuotePunct -> Bool+opens DoubleQuote = True+opens Apostrophe = True+opens OpeningSingleQuote = True+opens OpeningDoubleQuote = True+opens _ = False++closes :: QuotePunct -> Bool+closes DoubleQuote = True+closes Apostrophe = True+closes ClosingSingleQuote = True+closes ClosingDoubleQuote = True+closes _ = False++-- | Transform the following folk em dashes into proper em dashes+-- (@—@: @U+2014 EM DASH@):+--+-- - A hyphen (@-@: @U+002D HYPHEN-MINUS@) surrounded by spaces.+-- - Two or three consecutive hyphens (@--@ or @---@).+-- - A hangul vowel @ㅡ@ (@U+3161 HANGUL LETTER EU@) surrounded by spaces.+-- There are Korean people that use a hangul vowel @ㅡ@ ("eu") instead of+-- an em dash due to their ignorance or negligence.+transformEmDash :: [HtmlEntity] -> [HtmlEntity]+transformEmDash = transformText $ \ txt ->+ case parseOnly parser txt of+ Left _ -> error "unexpected error: failed to parse text node"+ Right t -> t+ where+ parser :: Parser Text+ parser = do+ chunks <- many' $ choice+ [ takeWhile1 $ \ c ->+ not (isSpace c || c `elem` (['&', '-', '\x3161'] :: Set Char))+ , emDash+ , Data.Text.singleton <$> anyChar+ ]+ endOfInput+ return $ Data.Text.concat chunks+ emDash :: Parser Text+ emDash = choice+ [ hyphens+ , takeWhile1 isSpace >> choice [eu, hyphen] >> takeWhile1 isSpace+ ] >> return "—"+ hyphens :: Parser Text+ hyphens = hyphen >> hyphen >> option "" hyphen+ hyphen :: Parser Text+ hyphen = choice $ Prelude.map string+ ["-", "-", "-", "-", "-", "-"]+ eu :: Parser Text+ eu = choice $ Prelude.map string+ ["\x3161", "ㅡ", "ㅡ", "ㅡ"]++transformText :: (Text -> Text) -> [HtmlEntity] -> [HtmlEntity]+transformText replace' = fmap $ \ case+ e@HtmlText { tagStack = stack, rawText = txt } ->+ if isPreservedTagStack stack+ then e+ else e { rawText = replace' txt }+ e ->+ e
+ src/Text/Seonbi/Trie.hs view
@@ -0,0 +1,17 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE TypeFamilies #-}+-- | This re-exports 'Data.Trie.Text'.+module Text.Seonbi.Trie+ ( module Data.Trie.Text+ ) where++import GHC.Exts++import Data.Text+import Data.Text.Lazy (toStrict)+import Data.Trie.Text++instance IsList (Trie a) where+ type Item (Trie a) = (Text, a)+ fromList = Data.Trie.Text.fromList+ toList trie = [(toStrict k, v) | (k, v) <- Data.Trie.Text.toList trie]
+ src/Text/Seonbi/Unihan/KHangul.hs view
@@ -0,0 +1,104 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeSynonymInstances #-}+module Text.Seonbi.Unihan.KHangul+ ( CharacterSet (..)+ , HanjaReadings+ , HanjaReadingCitation (..)+ , KHangulData+ , Purpose (..)+ , kHangulData+ , kHangulData'+ ) where++import Data.Either++import Data.Aeson+import Data.Attoparsec.Text+import Data.ByteString.Lazy (fromStrict)+import Data.FileEmbed+import Data.Map.Strict+import Data.Set hiding (empty)+import System.FilePath (takeDirectory, (</>))++-- $setup+-- >>> import qualified Text.Show.Unicode+-- >>> :set -interactive-print=Text.Show.Unicode.uprint++-- | Maps all Hanja characters to their possible readings.+type KHangulData = Map Char HanjaReadings++-- | All readings of a Hanja character.+type HanjaReadings = Map Char HanjaReadingCitation++-- | Represents what standard a reading of character belongs to and a purpose+-- of the reading.+data HanjaReadingCitation =+ HanjaReadingCitation CharacterSet (Set Purpose) deriving (Eq, Ord, Show)++-- | Represents character set standards for Korean writing system.+data CharacterSet+ -- | KS X 1001 (정보 교환용 부호계).+ = KS_X_1001+ -- | KS X 1002 (정보 교환용 부호 확장 세트).+ | KS_X_1002+ -- | Represents that a Hanja character is not included in any Korean+ -- character set standards.+ | NonStandard+ deriving (Eq, Ord, Show)++-- | Represents purposes of Hanja characters.+data Purpose+ -- | Basic Hanja for educational use (漢文敎育用基礎漢字), a subset of+ -- Hanja defined in 1972 by a South Korean standard for educational use.+ = Education+ -- | Hanja for personal names (人名用漢字).+ | PersonalName+ deriving (Eq, Ord, Show)++citationParser :: Parser HanjaReadingCitation+citationParser = do+ charset' <- option NonStandard charset+ purposes <- many' purpose+ return $ HanjaReadingCitation charset' $ Data.Set.fromList purposes+ where+ charset :: Parser CharacterSet+ charset = do+ d <- digit+ case d of+ '0' -> return KS_X_1001+ '1' -> return KS_X_1002+ c -> fail ("Invalid kHangul character set code: " ++ show c)+ purpose :: Parser Purpose+ purpose = do+ l <- letter+ case l of+ 'E' -> return Education+ 'N' -> return PersonalName+ c -> fail ("Invalid kHangul purpose code: " ++ show c)++instance FromJSON HanjaReadingCitation where+ parseJSON =+ withText "kHangul value (e.g., 0E, 1N, 0EN)" $ \ t ->+ case parseOnly (citationParser <* endOfInput) t of+ Right cite -> return cite+ Left msg -> fail msg++kHangulData' :: Either String KHangulData+kHangulData' = eitherDecode $+ fromStrict $(embedFile $ takeDirectory __FILE__ </> "kHangul.json")++-- | Data that map Hanja characters to their corresponding kHangul entries+-- (i.e., Hanja readings and citations).+--+-- >>> import Data.Map.Strict as M+-- >>> let Just entries = M.lookup '天' kHangulData+-- >>> entries+-- fromList [('천',HanjaReadingCitation KS_X_1001 (fromList [Education]))]+kHangulData :: KHangulData+kHangulData = fromRight empty kHangulData'++{- HLINT ignore "Unused LANGUAGE pragma" -}
+ src/Text/Seonbi/Unihan/kHangul.json view
@@ -0,0 +1,8413 @@+{+ "㒚":{"은": "N"},+ "㓗":{"결": "N"},+ "㔕":{"글": "N"},+ "㔡":{"별": "N"},+ "㗿":{"하": "N"},+ "㙯":{"예": "N"},+ "㛃":{"결": "N"},+ "㛄":{"의": "N"},+ "㛅":{"이": "N"},+ "㛦":{"람": "N"},+ "㜣":{"연": "N"},+ "㜯":{"희": "N"},+ "㜺":{"찬": "N"},+ "㞼":{"승": "N"},+ "㠌":{"기": "N"},+ "㠘":{"서": "N"},+ "㢃":{"랑": "N"},+ "㢺":{"현": "N"},+ "㣧":{"윤": "N"},+ "㣽":{"서": "N"},+ "㥠":{"서": "N"},+ "㥥":{"우": "N"},+ "㦃":{"산": "N"},+ "㦐":{"니": "N"},+ "㦥":{"헌": "N"},+ "㦶":{"용": "N"},+ "㨹":{"설": "N"},+ "㪤":{"필": "N"},+ "㫜":{"단": "N"},+ "㫶":{"주": "N"},+ "㬃":{"대": "N"},+ "㬣":{"대": "N"},+ "㭹":{"현": "N"},+ "㯳":{"경": "N"},+ "㰔":{"섭": "N"},+ "㰤":{"하": "N"},+ "㰭":{"후": "N"},+ "㲽":{"인": "N"},+ "㲾":{"우": "N"},+ "㳼":{"필": "N"},+ "㴗":{"유": "N"},+ "㵟":{"미": "N"},+ "㶼":{"애": "N"},+ "㷂":{"서": "N"},+ "㻄":{"보": "N"},+ "㻭":{"슬": "N"},+ "㻽":{"선": "N", "수": "N"},+ "㼄":{"기": "N"},+ "䀯":{"보": "N"},+ "䀴":{"영": "N"},+ "䁢":{"선": "N"},+ "䂩":{"연": "N"},+ "䃉":{"민": "N"},+ "䄷":{"석": "N"},+ "䆬":{"운": "N"},+ "䉙":{"운": "N"},+ "䎻":{"주": "N"},+ "䏇":{"표": "N"},+ "䏧":{"나": "N"},+ "䏪":{"이": "N"},+ "䑐":{"진": "N"},+ "䔒":{"배": "N"},+ "䗲":{"린": "N"},+ "䘘":{"소": "N", "어": "N"},+ "䚷":{"혜": "N"},+ "䚾":{"임": "N"},+ "䛔":{"나": "N"},+ "䛘":{"임": "N"},+ "䛝":{"노": "N"},+ "䜭":{"예": "N", "준": "N"},+ "䝬":{"주": "N"},+ "䝽":{"애": "N"},+ "䞟":{"백": "N"},+ "䡣":{"헌": "N"},+ "䢃":{"예": "N"},+ "䢖":{"건": "N", "율": "N"},+ "䢦":{"솔": "N"},+ "䤥":{"귀": "N"},+ "䦞":{"윤": "N"},+ "䦥":{"한": "N"},+ "䧋":{"현": "N"},+ "䨒":{"우": "N"},+ "䨭":{"소": "N"},+ "䪸":{"민": "N"},+ "䫟":{"운": "N", "혼": "N"},+ "䫨":{"오": "N"},+ "䫻":{"율": "N"},+ "䭓":{"안": "N", "온": "N"},+ "䭱":{"별": "N"},+ "䳟":{"명": "N"},+ "䳠":{"수": "N"},+ "䴛":{"소": "N"},+ "一":{"일": "0E"},+ "丁":{"정": "0E"},+ "七":{"칠": "0E"},+ "万":{"만": "0N"},+ "丈":{"장": "0E"},+ "三":{"삼": "0E"},+ "上":{"상": "0E"},+ "下":{"하": "0E"},+ "不":{"부": "0N", "불": "0E"},+ "丑":{"축": "0E"},+ "且":{"차": "0E"},+ "丕":{"비": "0N"},+ "世":{"세": "0E"},+ "丘":{"구": "0E"},+ "丙":{"병": "0E"},+ "丞":{"승": "0N"},+ "丟":{"주": "1N"},+ "並":{"병": "1N"},+ "丫":{"아": "1N"},+ "中":{"중": "0E"},+ "丰":{"봉": "1N"},+ "丱":{"관": "1N"},+ "串":{"곶": "0N", "관": "0N"},+ "丸":{"환": "0E"},+ "丹":{"단": "0E", "란": "0N"},+ "主":{"주": "0E"},+ "乂":{"예": "0N"},+ "乃":{"내": "0E"},+ "久":{"구": "0E"},+ "之":{"지": "0E"},+ "乍":{"사": "0N"},+ "乎":{"호": "0E"},+ "乏":{"핍": "0N"},+ "乖":{"괴": "0N"},+ "乘":{"승": "0E"},+ "乙":{"을": "0E"},+ "九":{"구": "0E"},+ "乞":{"걸": "0E"},+ "也":{"야": "0E"},+ "乧":{"둘": "1N"},+ "乫":{"갈": "0N"},+ "乬":{"걸": "1N"},+ "乭":{"돌": "0N"},+ "乳":{"유": "0E"},+ "乶":{"볼": "0N"},+ "乷":{"살": "0N"},+ "乺":{"솔": "N"},+ "乻":{"얼": "N"},+ "乼":{"줄": "1N"},+ "乾":{"건": "0E"},+ "亂":{"난": "0", "란": "0E"},+ "了":{"료": "0E", "요": "0"},+ "予":{"여": "0E"},+ "事":{"사": "0E"},+ "二":{"이": "0E"},+ "于":{"우": "0E"},+ "亏":{"우": "1"},+ "亐":{"울": "0"},+ "云":{"운": "0E"},+ "互":{"호": "0E"},+ "五":{"오": "0E"},+ "井":{"정": "0E"},+ "亘":{"긍": "0N", "선": "N"},+ "亙":{"긍": "1N"},+ "些":{"사": "0N"},+ "亜":{"아": "N"},+ "亞":{"아": "0E"},+ "亟":{"극": "1N"},+ "亡":{"망": "0E"},+ "亢":{"항": "0N"},+ "交":{"교": "0E"},+ "亥":{"해": "0E"},+ "亦":{"역": "0E"},+ "亨":{"형": "0E"},+ "享":{"향": "0E"},+ "京":{"경": "0E"},+ "亭":{"정": "0E"},+ "亮":{"량": "0N", "양": "0"},+ "亰":{"경": "N"},+ "亳":{"박": "1N"},+ "亴":{"우": "1N"},+ "亶":{"단": "0N"},+ "亹":{"미": "1N"},+ "人":{"인": "0E"},+ "什":{"십": "0N", "집": "0N"},+ "仁":{"인": "0E"},+ "仄":{"측": "0N"},+ "仆":{"부": "1"},+ "仇":{"구": "0N"},+ "今":{"금": "0E"},+ "介":{"개": "0E"},+ "仍":{"잉": "0N"},+ "仔":{"자": "0N"},+ "仕":{"사": "0E"},+ "他":{"타": "0E"},+ "仗":{"장": "0N"},+ "付":{"부": "0E"},+ "仙":{"선": "0E"},+ "仝":{"동": "0N"},+ "仞":{"인": "1N"},+ "仟":{"천": "0N"},+ "仡":{"흘": "1N"},+ "代":{"대": "0E"},+ "令":{"령": "0E", "영": "0"},+ "以":{"이": "0E"},+ "仮":{"가": "1"},+ "仰":{"앙": "0E"},+ "仲":{"중": "0E"},+ "仳":{"비": "1N"},+ "仵":{"오": "1N"},+ "件":{"건": "0E"},+ "价":{"개": "0N"},+ "任":{"임": "0E"},+ "份":{"빈": "N"},+ "仿":{"방": "1N"},+ "伀":{"종": "1N"},+ "企":{"기": "0E"},+ "伉":{"항": "0N"},+ "伊":{"이": "0N"},+ "伋":{"급": "0N"},+ "伍":{"오": "0N"},+ "伎":{"기": "0N"},+ "伏":{"복": "0E"},+ "伐":{"벌": "0E"},+ "休":{"휴": "0E"},+ "会":{"회": "N"},+ "伯":{"백": "0E"},+ "估":{"고": "1N"},+ "伴":{"반": "0E"},+ "伶":{"령": "0N"},+ "伸":{"신": "0E"},+ "伺":{"사": "0N"},+ "似":{"사": "0E"},+ "伽":{"가": "0N"},+ "伾":{"비": "N"},+ "佂":{"정": "1N"},+ "佃":{"전": "0N"},+ "但":{"단": "0E"},+ "佇":{"저": "0N"},+ "佈":{"포": "0N"},+ "佉":{"구": "1"},+ "佋":{"소": "1N"},+ "位":{"위": "0E"},+ "低":{"저": "0E"},+ "住":{"주": "0E"},+ "佐":{"좌": "0E"},+ "佑":{"우": "0N"},+ "体":{"분": "1N"},+ "佔":{"점": "1N"},+ "何":{"하": "0E"},+ "佖":{"필": "1N"},+ "佗":{"타": "1N"},+ "余":{"여": "0E"},+ "佚":{"일": "0N"},+ "佛":{"불": "0E"},+ "作":{"작": "0E"},+ "佝":{"구": "1N"},+ "佞":{"녕": "1N"},+ "佟":{"퉁": "1N"},+ "佩":{"패": "0N"},+ "佪":{"회": "1N"},+ "佯":{"양": "0N"},+ "佰":{"백": "0N"},+ "佳":{"가": "0E"},+ "佴":{"이": "N"},+ "佶":{"길": "0N"},+ "佸":{"괄": "1N"},+ "佹":{"궤": "1N"},+ "佺":{"전": "0N"},+ "佻":{"조": "1N"},+ "佼":{"교": "1N"},+ "佽":{"차": "1N"},+ "佾":{"일": "0N"},+ "使":{"사": "0E"},+ "侀":{"형": "N"},+ "侁":{"신": "0N"},+ "侃":{"간": "0N"},+ "侄":{"질": "0N"},+ "來":{"내": "0", "래": "0E"},+ "侈":{"치": "0N"},+ "侉":{"과": "1N"},+ "侊":{"광": "0N"},+ "例":{"례": "0E", "예": "0"},+ "侍":{"시": "0E"},+ "侎":{"미": "N"},+ "侏":{"주": "0N"},+ "侐":{"혁": "N"},+ "侑":{"유": "0N"},+ "侒":{"안": "N"},+ "侔":{"모": "1N"},+ "侖":{"륜": "0N"},+ "侗":{"동": "1N"},+ "侘":{"차": "0N"},+ "侚":{"순": "1N"},+ "供":{"공": "0E"},+ "侜":{"주": "1N"},+ "依":{"의": "0E"},+ "侮":{"모": "0E"},+ "侯":{"후": "0E"},+ "侲":{"진": "1N"},+ "侵":{"침": "0E"},+ "侶":{"려": "0N"},+ "侹":{"정": "N"},+ "侻":{"탈": "1N"},+ "便":{"변": "0N", "편": "0E"},+ "俁":{"우": "1N"},+ "係":{"계": "0E"},+ "促":{"촉": "0E"},+ "俄":{"아": "0N"},+ "俅":{"구": "1N"},+ "俉":{"오": "0N"},+ "俊":{"준": "0E"},+ "俌":{"보": "1N"},+ "俍":{"량": "N"},+ "俎":{"조": "0N"},+ "俏":{"소": "1", "초": "N"},+ "俐":{"리": "1N"},+ "俑":{"용": "0N"},+ "俒":{"혼": "N"},+ "俓":{"경": "0N"},+ "俔":{"현": "0N"},+ "俗":{"속": "0E"},+ "俘":{"부": "1N"},+ "俙":{"희": "N"},+ "俚":{"리": "0N"},+ "俛":{"면": "1N"},+ "保":{"보": "0E"},+ "俞":{"유": "N"},+ "俟":{"사": "0N"},+ "俠":{"협": "0N"},+ "信":{"신": "0E"},+ "俣":{"오": "1N"},+ "修":{"수": "0E"},+ "俯":{"부": "0N"},+ "俰":{"화": "1N"},+ "俱":{"구": "0E"},+ "俳":{"배": "0N"},+ "俴":{"천": "1N"},+ "俵":{"표": "0N"},+ "俶":{"숙": "1N"},+ "俸":{"봉": "0N"},+ "俺":{"엄": "0N"},+ "俾":{"비": "1N"},+ "倀":{"창": "1N"},+ "倂":{"병": "0N"},+ "倅":{"쉬": "1N"},+ "倆":{"량": "0N"},+ "倇":{"원": "N"},+ "倉":{"창": "0E"},+ "個":{"개": "0E"},+ "倍":{"배": "0E"},+ "倏":{"숙": "1N"},+ "們":{"문": "0N"},+ "倒":{"도": "0E"},+ "倓":{"담": "N"},+ "倔":{"굴": "1N"},+ "倖":{"행": "0N"},+ "倘":{"당": "1N"},+ "候":{"후": "0E"},+ "倚":{"의": "0N"},+ "倜":{"척": "0N"},+ "倞":{"경": "0N"},+ "借":{"차": "0E"},+ "倡":{"창": "0N"},+ "倢":{"첩": "1N"},+ "倣":{"방": "0E"},+ "値":{"치": "0E"},+ "倥":{"공": "1N"},+ "倦":{"권": "0N"},+ "倧":{"종": "0N"},+ "倨":{"거": "0N"},+ "倩":{"천": "1N"},+ "倪":{"예": "0N"},+ "倫":{"륜": "0E", "윤": "0"},+ "倬":{"탁": "0N"},+ "倭":{"왜": "0N"},+ "倮":{"라": "1N"},+ "倰":{"릉": "1N"},+ "倻":{"야": "0N"},+ "偃":{"언": "0N"},+ "偄":{"난": "1N"},+ "假":{"가": "0E"},+ "偈":{"게": "0N"},+ "偉":{"위": "0E"},+ "偊":{"우": "1N"},+ "偎":{"외": "1N"},+ "偏":{"편": "0E"},+ "偓":{"악": "1N"},+ "偕":{"해": "0N"},+ "偖":{"차": "1"},+ "偘":{"간": "1N"},+ "偙":{"제": "N"},+ "做":{"주": "0N"},+ "停":{"정": "0E"},+ "偠":{"요": "1N"},+ "偢":{"초": "1N"},+ "健":{"건": "0E"},+ "偦":{"서": "N"},+ "偪":{"핍": "1N"},+ "偰":{"설": "1N"},+ "偲":{"시": "1N"},+ "側":{"측": "0E"},+ "偵":{"정": "0N"},+ "偶":{"우": "0E"},+ "偸":{"투": "0N"},+ "傀":{"괴": "0N"},+ "傃":{"소": "N"},+ "傅":{"부": "0N"},+ "傋":{"강": "1N"},+ "傍":{"방": "0E"},+ "傑":{"걸": "0E"},+ "傒":{"혜": "1N"},+ "傔":{"겸": "1N"},+ "傖":{"창": "1N"},+ "傘":{"산": "0N"},+ "備":{"비": "0E"},+ "傚":{"효": "1N"},+ "傛":{"용": "1N"},+ "傝":{"탑": "1N"},+ "傞":{"사": "1N"},+ "傢":{"가": "1"},+ "催":{"최": "0E"},+ "傭":{"용": "0N"},+ "傮":{"조": "1N"},+ "傲":{"오": "0E"},+ "傳":{"전": "0E"},+ "傴":{"구": "1N"},+ "債":{"채": "0E"},+ "傷":{"상": "0E"},+ "傽":{"장": "1N"},+ "傾":{"경": "0E"},+ "傿":{"언": "1N"},+ "僂":{"루": "1N"},+ "僄":{"표": "1N"},+ "僅":{"근": "0E"},+ "僉":{"첨": "0N"},+ "僊":{"선": "0N"},+ "像":{"상": "0E"},+ "僑":{"교": "0N"},+ "僔":{"준": "N"},+ "僕":{"복": "0N"},+ "僖":{"희": "0N"},+ "僚":{"료": "0E", "요": "0"},+ "僛":{"기": "1N"},+ "僞":{"위": "0E"},+ "僢":{"천": "1N"},+ "僥":{"요": "0N"},+ "僦":{"추": "1N"},+ "僧":{"승": "0E"},+ "僩":{"한": "1N"},+ "僬":{"초": "1N"},+ "僭":{"참": "0N"},+ "僮":{"동": "1N"},+ "僵":{"강": "1N"},+ "價":{"가": "0E"},+ "僻":{"벽": "0N"},+ "僾":{"애": "1N"},+ "僿":{"사": "0N"},+ "儀":{"의": "0E"},+ "儁":{"준": "0N"},+ "儂":{"농": "1N"},+ "儃":{"천": "1N"},+ "億":{"억": "0E"},+ "儆":{"경": "0N"},+ "儇":{"현": "1N"},+ "儉":{"검": "0E"},+ "儋":{"담": "1N"},+ "儐":{"빈": "1N"},+ "儒":{"유": "0E"},+ "儓":{"대": "1N"},+ "儔":{"주": "1N"},+ "儕":{"제": "1N"},+ "儗":{"의": "1N"},+ "儘":{"진": "1N"},+ "儚":{"맹": "1"},+ "儛":{"무": "1N"},+ "儜":{"녕": "1N"},+ "償":{"상": "0E"},+ "儡":{"뢰": "0N"},+ "儢":{"려": "1N"},+ "儤":{"포": "1N"},+ "儥":{"육": "1N"},+ "儧":{"찬": "1N"},+ "優":{"우": "0E"},+ "儫":{"호": "1N"},+ "儱":{"롱": "1N"},+ "儲":{"저": "0N"},+ "儳":{"참": "1N"},+ "儵":{"숙": "1N"},+ "儷":{"려": "0N"},+ "儸":{"라": "N"},+ "儹":{"찬": "1N"},+ "儺":{"나": "0N"},+ "儻":{"당": "1N"},+ "儼":{"엄": "0N"},+ "儿":{"인": "N"},+ "兀":{"올": "0N"},+ "允":{"윤": "0N"},+ "元":{"원": "0E"},+ "兄":{"형": "0E"},+ "充":{"충": "0E"},+ "兆":{"조": "0E"},+ "兇":{"흉": "0N"},+ "先":{"선": "0E"},+ "光":{"광": "0E"},+ "克":{"극": "0E"},+ "兌":{"태": "0N"},+ "免":{"면": "0E"},+ "兎":{"토": "0N"},+ "児":{"아": "N"},+ "兒":{"아": "0E", "예": "N"},+ "兔":{"토": "N"},+ "兕":{"시": "1N"},+ "兖":{"연": "N"},+ "兗":{"연": "1N"},+ "党":{"당": "1"},+ "兜":{"두": "0N"},+ "兢":{"긍": "0N"},+ "入":{"입": "0E"},+ "內":{"내": "0E"},+ "全":{"전": "0E"},+ "兩":{"량": "0E", "양": "0"},+ "兪":{"유": "0N"},+ "八":{"팔": "0E"},+ "公":{"공": "0E"},+ "六":{"륙": "0E", "육": "0"},+ "兮":{"혜": "0E"},+ "共":{"공": "0E"},+ "兵":{"병": "0E"},+ "其":{"기": "0E"},+ "具":{"구": "0E"},+ "典":{"전": "0E"},+ "兼":{"겸": "0E"},+ "冀":{"기": "0N"},+ "冂":{"경": "N"},+ "円":{"엔": "0N"},+ "冉":{"염": "1N"},+ "冊":{"책": "0E"},+ "册":{"책": "N"},+ "再":{"재": "0E"},+ "冏":{"경": "1N"},+ "冑":{"주": "N"},+ "冒":{"모": "0E"},+ "冓":{"구": "1N"},+ "冕":{"면": "0N"},+ "冗":{"용": "0N"},+ "冘":{"유": "1N"},+ "冞":{"미": "N"},+ "冠":{"관": "0E"},+ "冢":{"총": "N"},+ "冣":{"취": "1N"},+ "冤":{"원": "1N"},+ "冥":{"명": "0E"},+ "冪":{"멱": "0N"},+ "冬":{"동": "0E"},+ "冰":{"빙": "1"},+ "冱":{"호": "1N"},+ "冲":{"충": "1N"},+ "冶":{"야": "0N"},+ "冷":{"냉": "0", "랭": "0E"},+ "冽":{"렬": "0N"},+ "冾":{"협": "N"},+ "凄":{"처": "0N"},+ "凅":{"고": "1N"},+ "准":{"준": "0N"},+ "凉":{"량": "0N", "양": "0"},+ "凊":{"청": "1N"},+ "凋":{"조": "0N"},+ "凌":{"능": "0", "릉": "0N"},+ "凍":{"동": "0E"},+ "凒":{"의": "1N"},+ "凔":{"창": "1N"},+ "凖":{"준": "N"},+ "凛":{"름": "1N"},+ "凜":{"늠": "0", "름": "0N"},+ "凝":{"응": "0E"},+ "凞":{"희": "0N"},+ "几":{"궤": "1N"},+ "凡":{"범": "0E"},+ "凩":{"목": "1"},+ "凭":{"빙": "1N"},+ "凰":{"황": "0N"},+ "凱":{"개": "0N"},+ "凳":{"등": "1N"},+ "凴":{"빙": "1"},+ "凶":{"흉": "0E"},+ "凸":{"철": "0N"},+ "凹":{"요": "0N"},+ "出":{"출": "0E"},+ "函":{"함": "0N"},+ "刀":{"도": "0E"},+ "刁":{"조": "1N"},+ "刃":{"인": "0N"},+ "分":{"분": "0E"},+ "切":{"절": "0E", "체": "0N"},+ "刈":{"예": "0N"},+ "刊":{"간": "0E"},+ "刎":{"문": "0N"},+ "刑":{"형": "0E"},+ "刓":{"완": "1N"},+ "刖":{"월": "1N"},+ "列":{"렬": "0E", "열": "0"},+ "初":{"초": "0E"},+ "判":{"판": "0E"},+ "別":{"별": "0E"},+ "刦":{"겁": "1N"},+ "刧":{"겁": "1N"},+ "利":{"리": "0E", "이": "0"},+ "刪":{"산": "0N"},+ "刮":{"괄": "0N"},+ "到":{"도": "0E"},+ "刱":{"창": "1N"},+ "刲":{"규": "1N"},+ "刳":{"고": "1N"},+ "制":{"제": "0E"},+ "刷":{"쇄": "0E"},+ "券":{"권": "0E"},+ "刹":{"찰": "0N"},+ "刺":{"자": "0E", "척": "0N"},+ "刻":{"각": "0E"},+ "剃":{"체": "0N"},+ "剄":{"경": "1N"},+ "剆":{"라": "N"},+ "則":{"칙": "0E"},+ "剉":{"좌": "1N"},+ "削":{"삭": "0E"},+ "剋":{"극": "0N"},+ "剌":{"랄": "0N"},+ "前":{"전": "0E"},+ "剔":{"척": "0N"},+ "剕":{"비": "1N"},+ "剖":{"부": "0N"},+ "剗":{"잔": "1N"},+ "剚":{"사": "1N"},+ "剛":{"강": "0E"},+ "剝":{"박": "0N"},+ "剞":{"기": "1N"},+ "剟":{"철": "1N"},+ "剡":{"섬": "0N"},+ "剩":{"잉": "0N"},+ "剪":{"전": "0N"},+ "副":{"부": "0E"},+ "割":{"할": "0E"},+ "剴":{"개": "1N"},+ "創":{"창": "0E"},+ "剷":{"산": "1N"},+ "剺":{"리": "1N"},+ "剽":{"표": "0N"},+ "剿":{"초": "0N"},+ "劂":{"궤": "1N"},+ "劃":{"획": "0E"},+ "劇":{"극": "0E"},+ "劈":{"벽": "0N"},+ "劉":{"류": "0N", "유": "0"},+ "劍":{"검": "0E"},+ "劑":{"제": "0N"},+ "劒":{"검": "0N"},+ "劓":{"의": "1N"},+ "劗":{"찬": "1N"},+ "劘":{"마": "1N"},+ "力":{"력": "0E", "역": "0"},+ "功":{"공": "0E"},+ "加":{"가": "0E"},+ "劣":{"렬": "0E", "열": "0"},+ "劤":{"근": "0N"},+ "劧":{"지": "N"},+ "助":{"조": "0E"},+ "努":{"노": "0E"},+ "劫":{"겁": "0N"},+ "劬":{"구": "1N"},+ "劭":{"소": "N", "초": "1"},+ "劮":{"일": "N"},+ "効":{"효": "N"},+ "劾":{"핵": "0N"},+ "勁":{"경": "0N"},+ "勃":{"발": "0N"},+ "勅":{"칙": "0N"},+ "勇":{"용": "0E"},+ "勉":{"면": "0E"},+ "勌":{"권": "1N"},+ "勍":{"경": "0N"},+ "勒":{"늑": "0", "륵": "0N"},+ "動":{"동": "0E"},+ "勖":{"욱": "0N"},+ "勘":{"감": "0N"},+ "務":{"무": "0E"},+ "勛":{"훈": "0N"},+ "勝":{"승": "0E"},+ "勞":{"노": "0", "로": "0E"},+ "募":{"모": "0E"},+ "勠":{"륙": "1N"},+ "勡":{"표": "1N"},+ "勢":{"세": "0E"},+ "勣":{"적": "0N"},+ "勤":{"근": "0E"},+ "勦":{"초": "1N"},+ "勭":{"동": "N"},+ "勲":{"훈": "N"},+ "勳":{"훈": "0N"},+ "勵":{"려": "0E", "여": "0"},+ "勸":{"권": "0E"},+ "勺":{"작": "0N"},+ "勻":{"균": "0N"},+ "勾":{"구": "0N"},+ "勿":{"물": "0E"},+ "匀":{"균": "N"},+ "匁":{"문": "1"},+ "匂":{"내": "1"},+ "匃":{"개": "1N"},+ "包":{"포": "0E"},+ "匈":{"흉": "0N"},+ "匊":{"국": "1N"},+ "匌":{"합": "1N"},+ "匍":{"포": "0N"},+ "匏":{"포": "0N"},+ "匐":{"복": "0N"},+ "匕":{"비": "0N"},+ "化":{"화": "0E"},+ "北":{"배": "0N", "북": "0E"},+ "匙":{"시": "0N"},+ "匠":{"장": "0N"},+ "匡":{"광": "0N"},+ "匣":{"갑": "0N"},+ "匧":{"협": "1N"},+ "匪":{"비": "0N"},+ "匯":{"회": "0N"},+ "匱":{"궤": "1N"},+ "匶":{"구": "1N"},+ "匸":{"혜": "N"},+ "匹":{"필": "0E"},+ "匽":{"언": "1N"},+ "匾":{"편": "1N"},+ "匿":{"닉": "0N", "익": "0"},+ "區":{"구": "0E"},+ "十":{"십": "0E"},+ "千":{"천": "0E"},+ "卄":{"입": "0N"},+ "卅":{"삽": "1N"},+ "升":{"승": "0N"},+ "午":{"오": "0E"},+ "卉":{"훼": "0N"},+ "半":{"반": "0E"},+ "卍":{"만": "0N"},+ "卑":{"비": "0E"},+ "卒":{"졸": "0E"},+ "卓":{"탁": "0E"},+ "協":{"협": "0E"},+ "南":{"남": "0E"},+ "博":{"박": "0E"},+ "卜":{"복": "0E"},+ "卞":{"변": "0N"},+ "占":{"점": "0E"},+ "卡":{"잡": "1N"},+ "卦":{"괘": "0N"},+ "卨":{"설": "0N"},+ "卬":{"앙": "1N"},+ "卮":{"치": "1N"},+ "卯":{"묘": "0E"},+ "印":{"인": "0E"},+ "危":{"위": "0E"},+ "卲":{"소": "1N"},+ "即":{"즉": "1N"},+ "却":{"각": "0E"},+ "卵":{"난": "0", "란": "0E"},+ "卷":{"권": "0E"},+ "卸":{"사": "1N"},+ "卹":{"휼": "1N"},+ "卺":{"근": "1"},+ "卻":{"각": "1N"},+ "卽":{"즉": "0E"},+ "卾":{"악": "1"},+ "卿":{"경": "0EN"},+ "厄":{"액": "0E"},+ "厎":{"지": "N"},+ "厓":{"애": "0N"},+ "厖":{"방": "1N"},+ "厘":{"리": "0N"},+ "厚":{"후": "0E"},+ "厝":{"조": "1N"},+ "原":{"원": "0E"},+ "厠":{"측": "0N"},+ "厥":{"궐": "0E"},+ "厦":{"하": "0N"},+ "厪":{"근": "1"},+ "厭":{"염": "0N"},+ "厮":{"시": "1N"},+ "厲":{"려": "1N"},+ "厳":{"엄": "N"},+ "厹":{"구": "1N"},+ "去":{"거": "0E"},+ "參":{"삼": "0N", "참": "0E"},+ "叅":{"참": "1"},+ "又":{"우": "0E"},+ "叉":{"차": "0N"},+ "及":{"급": "0E"},+ "友":{"우": "0E"},+ "双":{"쌍": "N"},+ "反":{"반": "0E"},+ "叔":{"숙": "0E"},+ "取":{"취": "0E"},+ "受":{"수": "0E"},+ "叙":{"서": "N"},+ "叛":{"반": "0E"},+ "叟":{"수": "1N"},+ "叡":{"예": "0N"},+ "叢":{"총": "0N"},+ "口":{"구": "0E"},+ "古":{"고": "0E"},+ "句":{"구": "0E", "귀": "0N"},+ "另":{"령": "1N"},+ "叨":{"도": "1N"},+ "叩":{"고": "0N"},+ "只":{"지": "0E"},+ "叫":{"규": "0E"},+ "召":{"소": "0E"},+ "叭":{"팔": "0N"},+ "叮":{"정": "1N"},+ "可":{"가": "0E"},+ "台":{"태": "0N"},+ "叱":{"질": "0N"},+ "史":{"사": "0E"},+ "右":{"우": "0E"},+ "叴":{"구": "1N"},+ "叵":{"파": "1N"},+ "叶":{"협": "1N"},+ "号":{"호": "N"},+ "司":{"사": "0E"},+ "吁":{"우": "1N"},+ "吃":{"흘": "0N"},+ "各":{"각": "0E"},+ "合":{"합": "0E"},+ "吉":{"길": "0E"},+ "吊":{"적": "0N"},+ "吋":{"촌": "1N"},+ "同":{"동": "0E"},+ "名":{"명": "0E"},+ "后":{"후": "0N"},+ "吏":{"리": "0E", "이": "0"},+ "吐":{"토": "0E"},+ "向":{"향": "0E"},+ "君":{"군": "0E"},+ "吝":{"린": "0N", "인": "0"},+ "吟":{"음": "0E"},+ "吠":{"폐": "0N"},+ "否":{"부": "0E"},+ "吩":{"분": "0N"},+ "含":{"함": "0E"},+ "听":{"은": "1N"},+ "吮":{"전": "1N"},+ "吱":{"지": "N"},+ "吳":{"오": "0N"},+ "吶":{"눌": "1N"},+ "吸":{"흡": "0E"},+ "吹":{"취": "0E"},+ "吻":{"문": "0N"},+ "吼":{"후": "0N"},+ "吽":{"후": "1N"},+ "吾":{"오": "0E"},+ "呀":{"하": "1N"},+ "呂":{"려": "0N", "여": "0"},+ "呆":{"매": "1N"},+ "呈":{"정": "0N"},+ "告":{"고": "0E"},+ "呎":{"척": "1"},+ "呑":{"탄": "0N"},+ "呝":{"액": "1N"},+ "呟":{"현": "N"},+ "呢":{"니": "1N"},+ "呤":{"령": "1N"},+ "呦":{"유": "1N"},+ "周":{"주": "0E"},+ "呪":{"주": "0N"},+ "呫":{"첩": "1N"},+ "呰":{"자": "1N"},+ "呱":{"고": "0N"},+ "味":{"미": "0E"},+ "呵":{"가": "0N"},+ "呶":{"노": "1N"},+ "呻":{"신": "0N"},+ "呼":{"호": "0E"},+ "命":{"명": "0E"},+ "呿":{"거": "1N"},+ "咀":{"저": "0N"},+ "咄":{"돌": "1N"},+ "咆":{"포": "0N"},+ "咇":{"필": "1N"},+ "咋":{"사": "1N"},+ "和":{"화": "0E"},+ "咍":{"해": "1N"},+ "咎":{"구": "0N"},+ "咏":{"영": "1N"},+ "咐":{"부": "0N"},+ "咖":{"가": "1"},+ "咠":{"집": "1N"},+ "咢":{"악": "1N"},+ "咤":{"타": "0N"},+ "咥":{"희": "1N"},+ "咨":{"자": "0N"},+ "咫":{"지": "0N"},+ "咬":{"교": "0N"},+ "咯":{"각": "1N"},+ "咲":{"소": "N"},+ "咳":{"해": "0N"},+ "咸":{"함": "0E"},+ "咻":{"휴": "1N"},+ "咼":{"괘": "1N"},+ "咽":{"열": "0N", "인": "0N"},+ "咿":{"이": "1N"},+ "哀":{"애": "0E"},+ "品":{"품": "0E"},+ "哂":{"신": "1N"},+ "哃":{"동": "1N"},+ "哄":{"홍": "0N"},+ "哆":{"치": "1N"},+ "哇":{"와": "1N"},+ "哈":{"합": "0N"},+ "哉":{"재": "0E"},+ "員":{"운": "N", "원": "0E"},+ "哥":{"가": "0N"},+ "哦":{"아": "1N"},+ "哨":{"초": "0N"},+ "哩":{"리": "1N"},+ "哭":{"곡": "0E"},+ "哮":{"효": "0N"},+ "哱":{"발": "1N"},+ "哲":{"철": "0E"},+ "哺":{"포": "0N"},+ "哽":{"경": "1N"},+ "哿":{"가": "1N"},+ "唄":{"패": "0N"},+ "唆":{"사": "0N"},+ "唇":{"진": "0N"},+ "唉":{"애": "1N"},+ "唎":{"리": "0N"},+ "唏":{"희": "1N"},+ "唐":{"당": "0E"},+ "唔":{"오": "1N"},+ "唜":{"말": "0N"},+ "唫":{"금": "1N"},+ "售":{"수": "1N"},+ "唯":{"유": "0E"},+ "唱":{"창": "0E"},+ "唳":{"려": "1N"},+ "唵":{"암": "0N"},+ "唹":{"어": "N"},+ "唼":{"삽": "1N"},+ "唾":{"타": "0N"},+ "啀":{"애": "1N"},+ "啂":{"누": "1N"},+ "啄":{"탁": "0N"},+ "商":{"상": "0E"},+ "啊":{"아": "N"},+ "問":{"문": "0E"},+ "啓":{"계": "0E"},+ "啖":{"담": "0N"},+ "啗":{"담": "1N"},+ "啜":{"철": "1N"},+ "啞":{"아": "0N"},+ "啣":{"함": "0N"},+ "啻":{"시": "1N"},+ "啼":{"제": "0N"},+ "啽":{"암": "1N"},+ "啾":{"추": "1N"},+ "啿":{"담": "N"},+ "喀":{"객": "0N"},+ "喁":{"옹": "1N"},+ "喃":{"남": "1N"},+ "善":{"선": "0E"},+ "喆":{"철": "0N"},+ "喇":{"나": "0N", "라": "0N"},+ "喉":{"후": "0N"},+ "喊":{"함": "0N"},+ "喋":{"첩": "1N"},+ "喑":{"음": "1N"},+ "喓":{"요": "1N"},+ "喔":{"악": "1N"},+ "喘":{"천": "0N"},+ "喙":{"훼": "0N"},+ "喚":{"환": "0N"},+ "喜":{"희": "0E"},+ "喝":{"갈": "0N"},+ "喞":{"즉": "1N"},+ "喟":{"위": "1N"},+ "喣":{"후": "1N"},+ "喤":{"황": "1N"},+ "喧":{"훤": "0N"},+ "喨":{"량": "1N"},+ "喩":{"유": "0N"},+ "喪":{"상": "0E"},+ "喫":{"끽": "0N"},+ "喬":{"교": "0N"},+ "單":{"단": "0E"},+ "喰":{"식": "1"},+ "嗃":{"학": "N"},+ "嗅":{"후": "0N"},+ "嗇":{"색": "0N"},+ "嗉":{"소": "1N"},+ "嗑":{"합": "1N"},+ "嗔":{"진": "0N"},+ "嗚":{"오": "0E"},+ "嗛":{"겸": "1N"},+ "嗜":{"기": "0N"},+ "嗟":{"차": "0N"},+ "嗠":{"락": "1N"},+ "嗢":{"올": "1N"},+ "嗣":{"사": "0N"},+ "嗤":{"치": "0N"},+ "嗷":{"오": "1N"},+ "嗽":{"수": "0N"},+ "嗾":{"주": "0N"},+ "嗿":{"탐": "1N"},+ "嘄":{"교": "1N"},+ "嘆":{"탄": "0N"},+ "嘈":{"조": "1N"},+ "嘉":{"가": "0N"},+ "嘌":{"표": "1N"},+ "嘍":{"루": "1N"},+ "嘎":{"알": "1N"},+ "嘏":{"가": "N", "하": "N"},+ "嘐":{"교": "1N"},+ "嘒":{"혜": "1N"},+ "嘔":{"구": "0N"},+ "嘖":{"책": "1N"},+ "嘗":{"상": "0E"},+ "嘩":{"화": "1N"},+ "嘬":{"최": "1N"},+ "嘯":{"소": "0N"},+ "嘲":{"조": "0N"},+ "嘴":{"취": "0N"},+ "嘶":{"시": "0N"},+ "嘷":{"호": "1N"},+ "嘸":{"무": "1N"},+ "嘹":{"료": "1N"},+ "嘻":{"희": "1N"},+ "嘿":{"묵": "1N"},+ "噁":{"오": "1N"},+ "噂":{"준": "1"},+ "噉":{"담": "1N"},+ "噋":{"톤": "1N"},+ "噍":{"초": "1N"},+ "噎":{"열": "1N"},+ "噏":{"흡": "1N"},+ "噓":{"허": "0N"},+ "噤":{"금": "1N"},+ "噥":{"농": "1N"},+ "器":{"기": "0E"},+ "噩":{"악": "1N"},+ "噪":{"조": "1N"},+ "噫":{"희": "0N"},+ "噬":{"서": "1N"},+ "噭":{"교": "1N"},+ "噯":{"애": "1N"},+ "噲":{"쾌": "1N"},+ "噴":{"분": "0N"},+ "噶":{"갈": "1N"},+ "噸":{"톤": "1"},+ "噺":{"신": "1"},+ "嚀":{"녕": "1N"},+ "嚄":{"획": "1N"},+ "嚆":{"효": "0N"},+ "嚇":{"하": "1N", "혁": "N"},+ "嚏":{"체": "1"},+ "嚙":{"교": "1N"},+ "嚚":{"은": "1N"},+ "嚥":{"연": "0N"},+ "嚧":{"로": "N"},+ "嚬":{"빈": "0N"},+ "嚮":{"향": "0N"},+ "嚳":{"곡": "1N"},+ "嚴":{"엄": "0E"},+ "嚶":{"앵": "1N"},+ "嚼":{"작": "0N"},+ "囀":{"전": "1N"},+ "囁":{"섭": "1N"},+ "囂":{"효": "1N"},+ "囃":{"잡": "1N"},+ "囈":{"예": "1N"},+ "囉":{"라": "1N"},+ "囊":{"낭": "0N"},+ "囍":{"희": "0"},+ "囑":{"촉": "0N"},+ "囚":{"수": "0E"},+ "四":{"사": "0E"},+ "回":{"회": "0E"},+ "囟":{"신": "1N"},+ "因":{"인": "0E"},+ "囦":{"연": "1N"},+ "囧":{"경": "N"},+ "囫":{"홀": "1N"},+ "囮":{"와": "1N"},+ "困":{"곤": "0E"},+ "囷":{"균": "1N"},+ "囹":{"령": "0N", "영": "0"},+ "固":{"고": "0E"},+ "国":{"국": "N"},+ "囿":{"유": "1N"},+ "圁":{"은": "1N"},+ "圂":{"혼": "1N"},+ "圃":{"포": "0N"},+ "圄":{"어": "0N"},+ "圇":{"륜": "N"},+ "圈":{"권": "0N"},+ "圉":{"어": "1N"},+ "圊":{"청": "1N"},+ "國":{"국": "0E"},+ "圍":{"위": "0E"},+ "園":{"원": "0E"},+ "圓":{"원": "0E"},+ "圖":{"도": "0E"},+ "團":{"단": "0E"},+ "圜":{"원": "1", "환": "N"},+ "土":{"토": "0E"},+ "圥":{"록": "1"},+ "在":{"재": "0E"},+ "圩":{"우": "N"},+ "圪":{"을": "N"},+ "圬":{"오": "1N"},+ "圭":{"규": "0N"},+ "圮":{"비": "1N"},+ "地":{"지": "0E"},+ "圻":{"기": "0N", "은": "N"},+ "圾":{"급": "1N"},+ "址":{"지": "0N"},+ "坁":{"지": "N"},+ "坂":{"판": "0N"},+ "均":{"균": "0E", "연": "N"},+ "坊":{"방": "0N"},+ "坌":{"분": "1N"},+ "坍":{"담": "0N"},+ "坎":{"감": "0N"},+ "坏":{"배": "1N"},+ "坐":{"좌": "0E"},+ "坑":{"갱": "0N"},+ "坡":{"파": "0N"},+ "坤":{"곤": "0E"},+ "坦":{"탄": "0N"},+ "坧":{"척": "1N"},+ "坨":{"이": "1", "타": "N"},+ "坩":{"감": "1N"},+ "坪":{"평": "0N"},+ "坮":{"대": "0N"},+ "坯":{"배": "1"},+ "坰":{"경": "0N"},+ "坱":{"앙": "1N"},+ "坳":{"요": "1N"},+ "坵":{"구": "0N"},+ "坷":{"가": "1N"},+ "坸":{"구": "1N"},+ "坻":{"지": "1N"},+ "坼":{"탁": "0N"},+ "垂":{"수": "0E"},+ "垈":{"대": "0N"},+ "型":{"형": "0N"},+ "垌":{"동": "1N"},+ "垓":{"해": "0N"},+ "垕":{"후": "1N"},+ "垞":{"타": "1", "택": "N"},+ "垠":{"은": "0N"},+ "垢":{"구": "0N"},+ "垣":{"원": "0N"},+ "垤":{"질": "1N"},+ "垸":{"완": "1N"},+ "垽":{"은": "1N"},+ "埃":{"애": "0N"},+ "埆":{"각": "1N"},+ "埇":{"용": "0N"},+ "埈":{"준": "0N"},+ "埉":{"협": "1N"},+ "埋":{"매": "0E"},+ "城":{"성": "0EN"},+ "埏":{"연": "1N"},+ "埑":{"철": "1N"},+ "埒":{"랄": "1N"},+ "埜":{"야": "1N"},+ "域":{"역": "0E"},+ "埠":{"부": "0N"},+ "埤":{"비": "1N"},+ "埩":{"정": "N"},+ "埭":{"태": "1N"},+ "埮":{"담": "N"},+ "埰":{"채": "0N"},+ "埳":{"감": "1N"},+ "埴":{"식": "0N"},+ "埶":{"예": "N"},+ "執":{"집": "0E"},+ "培":{"배": "0E"},+ "基":{"기": "0E"},+ "埻":{"준": "1N"},+ "埼":{"기": "0N"},+ "埽":{"소": "1N"},+ "堀":{"굴": "0N"},+ "堂":{"당": "0E"},+ "堃":{"곤": "1N"},+ "堄":{"예": "N"},+ "堅":{"견": "0E"},+ "堆":{"퇴": "0N"},+ "堈":{"강": "0N"},+ "堉":{"육": "0N"},+ "堊":{"악": "0N"},+ "堋":{"붕": "1N"},+ "堗":{"돌": "1N"},+ "堙":{"인": "1N"},+ "堝":{"과": "1N"},+ "堞":{"첩": "0N"},+ "堠":{"후": "1N"},+ "堡":{"보": "0N"},+ "堣":{"우": "1N"},+ "堤":{"제": "0E"},+ "堦":{"계": "1N"},+ "堧":{"연": "0N"},+ "堪":{"감": "0N"},+ "堭":{"황": "N"},+ "堯":{"요": "0N"},+ "堰":{"언": "0N"},+ "報":{"보": "0E"},+ "場":{"장": "0E"},+ "堵":{"도": "0N"},+ "堺":{"계": "0N"},+ "塀":{"병": "1"},+ "塉":{"척": "1N"},+ "塊":{"괴": "0E"},+ "塋":{"영": "0N"},+ "塌":{"탑": "1N"},+ "塍":{"승": "1N"},+ "塏":{"개": "0N"},+ "塐":{"소": "1N"},+ "塑":{"소": "0N"},+ "塒":{"시": "1N"},+ "塔":{"탑": "0E"},+ "塗":{"도": "0E"},+ "塘":{"당": "0N"},+ "塙":{"고": "1"},+ "塚":{"총": "0N"},+ "塞":{"새": "0E", "색": "0N"},+ "塡":{"전": "0N", "진": "N"},+ "塢":{"오": "0N"},+ "塤":{"훈": "0N"},+ "塩":{"염": "1"},+ "塵":{"진": "0N"},+ "塹":{"참": "0N"},+ "塼":{"전": "0N"},+ "塽":{"상": "1N"},+ "塾":{"숙": "0N"},+ "墀":{"지": "1N"},+ "墁":{"만": "1N"},+ "境":{"경": "0E"},+ "墅":{"서": "0N"},+ "墉":{"용": "0N"},+ "墊":{"점": "1N"},+ "墌":{"척": "N"},+ "墍":{"기": "1N"},+ "墐":{"근": "1N"},+ "墓":{"묘": "0E"},+ "墜":{"추": "0N"},+ "墝":{"요": "1N"},+ "增":{"증": "0E"},+ "墟":{"허": "0N"},+ "墡":{"선": "1N"},+ "墣":{"복": "1N"},+ "墨":{"묵": "0E"},+ "墩":{"돈": "0N"},+ "墫":{"준": "1N"},+ "墮":{"타": "0E"},+ "墰":{"담": "1N"},+ "墱":{"등": "1N"},+ "墳":{"분": "0E"},+ "墺":{"오": "0N"},+ "墻":{"장": "0E"},+ "墾":{"간": "0N"},+ "壁":{"벽": "0E"},+ "壃":{"강": "1N"},+ "壅":{"옹": "0N"},+ "壇":{"단": "0E"},+ "壎":{"훈": "0N"},+ "壑":{"학": "0N"},+ "壓":{"압": "0E"},+ "壔":{"도": "1N"},+ "壕":{"호": "0N"},+ "壘":{"누": "0", "루": "0N"},+ "壙":{"광": "0N"},+ "壚":{"로": "1N"},+ "壜":{"담": "1N"},+ "壝":{"유": "1N"},+ "壞":{"괴": "0E"},+ "壟":{"농": "0", "롱": "0N"},+ "壡":{"예": "N"},+ "壤":{"양": "0E"},+ "士":{"사": "0E"},+ "壬":{"임": "0E"},+ "壮":{"장": "N"},+ "壯":{"장": "0E"},+ "壹":{"일": "0N"},+ "壺":{"호": "0N"},+ "壻":{"서": "0N"},+ "壽":{"수": "0E"},+ "夆":{"봉": "1N"},+ "夈":{"재": "1N"},+ "夏":{"하": "0E"},+ "夐":{"형": "1N"},+ "夔":{"기": "0N"},+ "夕":{"석": "0E"},+ "外":{"외": "0E"},+ "夙":{"숙": "0N"},+ "多":{"다": "0E"},+ "夛":{"다": "N"},+ "夜":{"야": "0E"},+ "夢":{"몽": "0E"},+ "夤":{"인": "1N"},+ "夥":{"과": "1N"},+ "大":{"대": "0E"},+ "天":{"천": "0E"},+ "太":{"태": "0E"},+ "夫":{"부": "0E"},+ "夬":{"쾌": "1N"},+ "夭":{"요": "0N"},+ "央":{"앙": "0E"},+ "夯":{"항": "1N"},+ "失":{"실": "0E"},+ "夲":{"도": "N"},+ "夷":{"이": "0E"},+ "夸":{"과": "1N"},+ "夽":{"운": "N"},+ "夾":{"협": "0N"},+ "奄":{"엄": "0N"},+ "奇":{"기": "0E"},+ "奈":{"나": "0N", "내": "0E"},+ "奉":{"봉": "0E"},+ "奌":{"점": "N"},+ "奎":{"규": "0N"},+ "奏":{"주": "0E"},+ "奐":{"환": "0N"},+ "契":{"계": "0E", "글": "0N", "설": "N"},+ "奓":{"차": "1"},+ "奔":{"분": "0E"},+ "奕":{"혁": "0N"},+ "套":{"투": "0N"},+ "奘":{"장": "1N"},+ "奚":{"해": "0E"},+ "奜":{"비": "N"},+ "奠":{"전": "0N"},+ "奢":{"사": "0N"},+ "奧":{"오": "0N"},+ "奩":{"렴": "1"},+ "奪":{"탈": "0E"},+ "奫":{"윤": "0N"},+ "奬":{"장": "0E"},+ "奭":{"석": "0N"},+ "奮":{"분": "0E"},+ "奲":{"차": "N"},+ "女":{"녀": "0E", "여": "0"},+ "奴":{"노": "0E"},+ "奶":{"내": "1N"},+ "奸":{"간": "0N"},+ "好":{"호": "0E"},+ "如":{"여": "0E"},+ "妃":{"비": "0E"},+ "妄":{"망": "0E"},+ "妊":{"임": "0N"},+ "妌":{"정": "N"},+ "妍":{"연": "N"},+ "妑":{"파": "1N"},+ "妒":{"투": "1N"},+ "妓":{"기": "0N"},+ "妖":{"요": "0N"},+ "妗":{"금": "0N"},+ "妙":{"묘": "0E"},+ "妝":{"장": "1N"},+ "妣":{"비": "1N"},+ "妤":{"여": "N"},+ "妥":{"타": "0E"},+ "妧":{"완": "1N"},+ "妨":{"방": "0E"},+ "妬":{"투": "0N"},+ "妯":{"축": "1N"},+ "妲":{"달": "1N"},+ "妵":{"주": "N"},+ "妶":{"현": "N"},+ "妸":{"아": "N"},+ "妹":{"매": "0E"},+ "妻":{"처": "0E"},+ "妾":{"첩": "0E"},+ "妿":{"아": "N"},+ "姁":{"후": "N"},+ "姃":{"정": "0N"},+ "姆":{"모": "0N"},+ "姈":{"령": "1N"},+ "姉":{"자": "0N"},+ "姊":{"자": "E"},+ "始":{"시": "0E"},+ "姍":{"산": "1N"},+ "姐":{"저": "0N"},+ "姑":{"고": "0E"},+ "姒":{"사": "1N"},+ "姓":{"성": "0E"},+ "委":{"위": "0E"},+ "姙":{"임": "0N"},+ "姚":{"요": "0N"},+ "姜":{"강": "0N"},+ "姝":{"주": "0N"},+ "姞":{"길": "1N"},+ "姢":{"연": "N"},+ "姣":{"교": "1N"},+ "姤":{"구": "1N"},+ "姥":{"모": "1N"},+ "姦":{"간": "0E"},+ "姨":{"이": "0N"},+ "姪":{"질": "0E"},+ "姫":{"희": "N"},+ "姬":{"희": "0N"},+ "姮":{"항": "0N"},+ "姰":{"순": "N"},+ "姲":{"안": "N"},+ "姷":{"유": "N"},+ "姸":{"연": "0N"},+ "姹":{"차": "N"},+ "姺":{"신": "1N"},+ "姻":{"인": "0E"},+ "姼":{"제": "N"},+ "姿":{"자": "0E"},+ "威":{"위": "0E"},+ "娃":{"왜": "0N"},+ "娉":{"빙": "1N"},+ "娊":{"현": "N"},+ "娍":{"성": "N"},+ "娑":{"사": "0N"},+ "娓":{"미": "1N"},+ "娘":{"낭": "0E"},+ "娙":{"형": "1N"},+ "娛":{"오": "0E"},+ "娜":{"나": "0N"},+ "娟":{"연": "0N"},+ "娠":{"신": "0N"},+ "娣":{"제": "1N"},+ "娥":{"아": "0N"},+ "娧":{"태": "1N"},+ "娩":{"만": "0N"},+ "娫":{"연": "N"},+ "娭":{"애": "1N"},+ "娵":{"추": "1N"},+ "娶":{"취": "0N"},+ "娼":{"창": "0N"},+ "娿":{"아": "1N"},+ "婀":{"아": "1N"},+ "婁":{"루": "0N"},+ "婆":{"파": "0N"},+ "婇":{"채": "N"},+ "婉":{"완": "0N", "원": "N"},+ "婋":{"호": "N", "효": "N"},+ "婌":{"숙": "1N"},+ "婐":{"와": "1N"},+ "婑":{"유": "N"},+ "婚":{"혼": "0E"},+ "婠":{"완": "N"},+ "婢":{"비": "0E"},+ "婣":{"인": "1N"},+ "婦":{"부": "0E"},+ "婧":{"정": "1N", "청": "N"},+ "婩":{"안": "N"},+ "婪":{"람": "1N"},+ "婭":{"아": "N"},+ "婲":{"화": "1"},+ "婷":{"정": "1N"},+ "婿":{"서": "1N"},+ "媄":{"미": "1N"},+ "媍":{"부": "1N"},+ "媐":{"이": "N"},+ "媒":{"매": "0E"},+ "媓":{"황": "1N"},+ "媕":{"암": "1N"},+ "媚":{"미": "0N"},+ "媛":{"원": "0N"},+ "媞":{"시": "N", "제": "N"},+ "媟":{"설": "1N"},+ "媢":{"모": "1N"},+ "媤":{"시": "0N"},+ "媧":{"왜": "1N"},+ "媪":{"오": "1", "온": "N"},+ "媳":{"식": "1N"},+ "媵":{"잉": "1N"},+ "媺":{"미": "1N"},+ "媻":{"반": "1N"},+ "媼":{"온": "1N"},+ "媽":{"마": "1N"},+ "媾":{"구": "1N"},+ "媿":{"괴": "1N"},+ "嫁":{"가": "0N"},+ "嫂":{"수": "0N"},+ "嫄":{"원": "0N"},+ "嫈":{"앵": "1N"},+ "嫉":{"질": "0N"},+ "嫋":{"뇨": "1N"},+ "嫌":{"혐": "0E"},+ "嫕":{"예": "N"},+ "嫖":{"표": "1N"},+ "嫗":{"구": "1N"},+ "嫙":{"선": "1N"},+ "嫚":{"만": "1N"},+ "嫛":{"예": "1N"},+ "嫝":{"강": "N"},+ "嫠":{"리": "1N"},+ "嫡":{"적": "0N"},+ "嫢":{"규": "1N"},+ "嫣":{"언": "1N"},+ "嫤":{"근": "N"},+ "嫥":{"전": "1N"},+ "嫦":{"항": "0N"},+ "嫩":{"눈": "0N"},+ "嫫":{"모": "1N"},+ "嫭":{"호": "1N"},+ "嫮":{"호": "1N"},+ "嫯":{"오": "1N"},+ "嫶":{"초": "1N"},+ "嫺":{"한": "1N"},+ "嫻":{"한": "1N"},+ "嫽":{"료": "1N"},+ "嬀":{"규": "1N"},+ "嬅":{"화": "0N"},+ "嬈":{"요": "1N"},+ "嬉":{"희": "0N"},+ "嬋":{"선": "0N"},+ "嬌":{"교": "0N"},+ "嬖":{"폐": "0N"},+ "嬙":{"장": "1N"},+ "嬛":{"현": "1N"},+ "嬥":{"조": "1N"},+ "嬨":{"자": "1N"},+ "嬪":{"빈": "0N"},+ "嬭":{"내": "1N"},+ "嬰":{"영": "1N"},+ "嬲":{"뇨": "1N"},+ "嬴":{"영": "1N"},+ "嬾":{"란": "1N"},+ "嬿":{"연": "1N"},+ "孀":{"상": "0N"},+ "孃":{"양": "0N"},+ "孅":{"섬": "1N"},+ "孌":{"련": "1N"},+ "子":{"자": "0E"},+ "孑":{"혈": "0N"},+ "孔":{"공": "0E"},+ "孕":{"잉": "0N"},+ "孖":{"자": "1N"},+ "字":{"자": "0E"},+ "存":{"존": "0E"},+ "孚":{"부": "0N"},+ "孛":{"패": "1N"},+ "孜":{"자": "0N"},+ "孝":{"효": "0E"},+ "孟":{"맹": "0E"},+ "孡":{"태": "1N"},+ "季":{"계": "0E"},+ "孤":{"고": "0E"},+ "孥":{"노": "1N"},+ "学":{"학": "N"},+ "孩":{"해": "0N"},+ "孫":{"손": "0E"},+ "孰":{"숙": "0E"},+ "孱":{"잔": "0N"},+ "孵":{"부": "0N"},+ "孶":{"자": "1N"},+ "學":{"학": "0E"},+ "孺":{"유": "0N"},+ "孼":{"얼": "0N"},+ "孿":{"산": "1N"},+ "宁":{"저": "1N"},+ "宂":{"용": "1N"},+ "宅":{"댁": "0N", "택": "0E"},+ "宇":{"우": "0E"},+ "守":{"수": "0E"},+ "安":{"안": "0E"},+ "宊":{"가": "1"},+ "宋":{"송": "0N"},+ "完":{"완": "0E"},+ "宏":{"굉": "0N"},+ "宓":{"복": "0N"},+ "宕":{"탕": "0N"},+ "宖":{"횡": "0N"},+ "宗":{"종": "0E"},+ "官":{"관": "0E"},+ "宙":{"주": "0E"},+ "定":{"정": "0E"},+ "宛":{"완": "0N"},+ "宜":{"의": "0E"},+ "宝":{"보": "N"},+ "実":{"실": "N"},+ "客":{"객": "0E"},+ "宣":{"선": "0E"},+ "室":{"실": "0E"},+ "宥":{"유": "0N"},+ "宦":{"환": "0N"},+ "宬":{"성": "0N"},+ "宮":{"궁": "0E"},+ "宰":{"재": "0E"},+ "害":{"해": "0E"},+ "宴":{"연": "0E"},+ "宵":{"소": "0N"},+ "家":{"가": "0E"},+ "宸":{"신": "0N"},+ "容":{"용": "0E"},+ "宿":{"수": "N", "숙": "0E"},+ "寀":{"채": "0N"},+ "寂":{"적": "0E"},+ "寃":{"원": "0N"},+ "寄":{"기": "0E"},+ "寅":{"인": "0E"},+ "密":{"밀": "0E"},+ "寇":{"구": "0N"},+ "富":{"부": "0E"},+ "寐":{"매": "0N"},+ "寒":{"한": "0E"},+ "寓":{"우": "0N"},+ "寔":{"식": "0N"},+ "寖":{"침": "1N"},+ "寗":{"녕": "0N"},+ "寘":{"치": "1N"},+ "寛":{"관": "N"},+ "寞":{"막": "0N"},+ "察":{"찰": "0E"},+ "寡":{"과": "0E"},+ "寢":{"침": "0E"},+ "寤":{"오": "0N"},+ "寥":{"요": "0"},+ "實":{"실": "0E"},+ "寧":{"녕": "0E", "령": "0", "영": "0"},+ "寨":{"채": "0N"},+ "審":{"심": "0E"},+ "寫":{"사": "0E"},+ "寬":{"관": "0E"},+ "寭":{"혜": "1N"},+ "寮":{"료": "0N", "요": "0"},+ "寯":{"준": "0N"},+ "寰":{"환": "1N"},+ "寵":{"총": "0N"},+ "寶":{"보": "0E"},+ "寸":{"촌": "0E"},+ "寺":{"사": "0E"},+ "寿":{"수": "N"},+ "封":{"봉": "0E"},+ "射":{"사": "0E"},+ "尅":{"극": "1N"},+ "将":{"장": "N"},+ "將":{"장": "0E"},+ "專":{"전": "0E"},+ "尉":{"위": "0N"},+ "尊":{"존": "0E"},+ "尋":{"심": "0E"},+ "尌":{"주": "1N"},+ "對":{"대": "0E"},+ "導":{"도": "0E"},+ "小":{"소": "0E"},+ "少":{"소": "0E"},+ "尔":{"이": "1N"},+ "尖":{"첨": "0E"},+ "尙":{"상": "0E"},+ "尟":{"선": "1N"},+ "尠":{"선": "1"},+ "尤":{"우": "0E"},+ "尨":{"방": "0N"},+ "尫":{"왕": "1"},+ "就":{"취": "0E"},+ "尸":{"시": "0N"},+ "尹":{"윤": "0N"},+ "尺":{"척": "0E"},+ "尻":{"고": "0N"},+ "尼":{"니": "0N"},+ "尽":{"진": "N"},+ "尾":{"미": "0E"},+ "尿":{"뇨": "0N", "요": "0"},+ "局":{"국": "0E"},+ "屁":{"비": "1N"},+ "居":{"거": "0E"},+ "屆":{"계": "0N"},+ "屇":{"전": "1N"},+ "屈":{"굴": "0E"},+ "屋":{"옥": "0E"},+ "屍":{"시": "0N"},+ "屎":{"시": "0N"},+ "屐":{"극": "1N"},+ "屑":{"설": "0N"},+ "展":{"전": "0E"},+ "屛":{"병": "0E"},+ "屠":{"도": "0N"},+ "屢":{"누": "0", "루": "0E"},+ "層":{"층": "0E"},+ "履":{"리": "0E", "이": "0"},+ "屨":{"구": "1N"},+ "屬":{"속": "0E"},+ "屯":{"둔": "0E"},+ "山":{"산": "0E"},+ "屳":{"선": "1N"},+ "屹":{"흘": "0N"},+ "屺":{"기": "1N"},+ "岈":{"하": "1N"},+ "岊":{"절": "1N"},+ "岌":{"급": "1N"},+ "岏":{"완": "1N"},+ "岐":{"기": "0N"},+ "岑":{"잠": "0N"},+ "岒":{"겸": "1N"},+ "岔":{"차": "1N"},+ "岝":{"작": "1N"},+ "岡":{"강": "0N"},+ "岣":{"구": "1N"},+ "岥":{"파": "1N"},+ "岦":{"립": "1N"},+ "岧":{"초": "1N"},+ "岨":{"저": "1N"},+ "岩":{"암": "0N"},+ "岪":{"불": "1N"},+ "岫":{"수": "0N"},+ "岬":{"갑": "0N"},+ "岭":{"령": "1N"},+ "岱":{"대": "0N"},+ "岳":{"악": "0E"},+ "岵":{"호": "0N"},+ "岷":{"민": "0N"},+ "岸":{"안": "0E"},+ "岺":{"령": "0N"},+ "岾":{"점": "0N"},+ "峀":{"수": "0N"},+ "峋":{"순": "N"},+ "峒":{"동": "1N"},+ "峙":{"치": "0N"},+ "峠":{"상": "0N"},+ "峨":{"아": "0N"},+ "峩":{"아": "1N"},+ "峭":{"초": "1N"},+ "峯":{"봉": "0E"},+ "峰":{"봉": "0N"},+ "峱":{"노": "1N"},+ "峴":{"현": "0N"},+ "島":{"도": "0E"},+ "峻":{"준": "0N"},+ "峽":{"협": "0N"},+ "崆":{"공": "1N"},+ "崇":{"숭": "0E"},+ "崍":{"래": "0N"},+ "崎":{"기": "0N"},+ "崐":{"곤": "1N"},+ "崑":{"곤": "0N"},+ "崔":{"최": "0N"},+ "崕":{"애": "1N"},+ "崖":{"애": "0N"},+ "崗":{"강": "0N"},+ "崘":{"륜": "N"},+ "崙":{"륜": "0N", "윤": "0"},+ "崛":{"굴": "1N"},+ "崟":{"음": "1N"},+ "崢":{"쟁": "1N"},+ "崤":{"효": "1N"},+ "崦":{"엄": "1N"},+ "崧":{"숭": "0N"},+ "崩":{"붕": "0E"},+ "崴":{"외": "1N"},+ "崽":{"재": "1N"},+ "嵁":{"감": "1N"},+ "嵂":{"률": "1N"},+ "嵄":{"미": "N"},+ "嵋":{"미": "0N"},+ "嵌":{"감": "0N"},+ "嵎":{"우": "1N"},+ "嵐":{"남": "0", "람": "0N"},+ "嵓":{"암": "1N"},+ "嵔":{"외": "1N"},+ "嵩":{"숭": "0N"},+ "嵬":{"외": "0N"},+ "嵯":{"차": "0N"},+ "嵱":{"용": "1N"},+ "嶁":{"루": "1N"},+ "嶂":{"장": "1N"},+ "嶄":{"참": "1N"},+ "嶆":{"조": "N"},+ "嶇":{"구": "0N"},+ "嶋":{"도": "0N"},+ "嶒":{"증": "1N"},+ "嶔":{"금": "1N"},+ "嶕":{"초": "1N"},+ "嶙":{"린": "1N"},+ "嶝":{"등": "0N"},+ "嶠":{"교": "0N"},+ "嶢":{"요": "0N"},+ "嶧":{"역": "1N"},+ "嶪":{"업": "0N"},+ "嶫":{"업": "1N"},+ "嶮":{"험": "1N"},+ "嶰":{"해": "1N"},+ "嶷":{"의": "1N"},+ "嶸":{"영": "0N"},+ "嶺":{"령": "0E", "영": "0"},+ "嶼":{"서": "0N"},+ "嶽":{"악": "0N"},+ "嶾":{"은": "N"},+ "巉":{"참": "1N"},+ "巋":{"규": "1N"},+ "巍":{"외": "0N"},+ "巑":{"찬": "1N"},+ "巒":{"만": "0N"},+ "巓":{"전": "1N"},+ "巖":{"암": "0E"},+ "巚":{"헌": "1N"},+ "川":{"천": "0E"},+ "州":{"주": "0E"},+ "巠":{"경": "N"},+ "巡":{"순": "0E"},+ "巢":{"소": "0N"},+ "工":{"공": "0E"},+ "左":{"좌": "0E"},+ "巧":{"교": "0E"},+ "巨":{"거": "0E"},+ "巫":{"무": "0N"},+ "差":{"차": "0E"},+ "己":{"기": "0E"},+ "已":{"이": "0E"},+ "巳":{"사": "0E"},+ "巴":{"파": "0N"},+ "巵":{"치": "1"},+ "巷":{"항": "0E"},+ "巸":{"이": "N"},+ "巹":{"근": "1N"},+ "巽":{"손": "0N"},+ "巾":{"건": "0N"},+ "市":{"시": "0E"},+ "布":{"포": "0E"},+ "帆":{"범": "0N"},+ "帉":{"분": "1N"},+ "希":{"희": "0E"},+ "帑":{"탕": "0N"},+ "帕":{"말": "1N"},+ "帖":{"첩": "0N"},+ "帙":{"질": "0N"},+ "帚":{"추": "1N"},+ "帛":{"백": "0N"},+ "帝":{"제": "0E"},+ "帠":{"예": "N"},+ "帥":{"솔": "N", "수": "0E"},+ "帨":{"세": "1N"},+ "師":{"사": "0E"},+ "席":{"석": "0E"},+ "帳":{"장": "0E"},+ "帶":{"대": "0E"},+ "帷":{"유": "1N"},+ "常":{"상": "0E"},+ "帽":{"모": "0N"},+ "帿":{"후": "0N"},+ "幀":{"정": "0N"},+ "幃":{"위": "1N"},+ "幄":{"악": "0N"},+ "幅":{"폭": "0E"},+ "幇":{"방": "0N"},+ "幌":{"황": "0N"},+ "幎":{"멱": "1N"},+ "幔":{"만": "1N"},+ "幕":{"막": "0E"},+ "幘":{"책": "1N"},+ "幞":{"복": "1N"},+ "幟":{"치": "0N"},+ "幡":{"번": "0N"},+ "幢":{"당": "0N"},+ "幣":{"폐": "0E"},+ "幨":{"첨": "1N"},+ "幪":{"몽": "1N"},+ "幫":{"방": "1N"},+ "幬":{"주": "1N"},+ "幰":{"헌": "1N"},+ "幱":{"란": "1N"},+ "干":{"간": "0E"},+ "平":{"평": "0E"},+ "年":{"년": "0E", "연": "0"},+ "并":{"병": "N"},+ "幷":{"병": "0N"},+ "幸":{"행": "0E"},+ "幹":{"간": "0E"},+ "幺":{"요": "1N"},+ "幻":{"환": "0N"},+ "幼":{"유": "0E"},+ "幽":{"유": "0E"},+ "幾":{"기": "0E"},+ "广":{"엄": "1N"},+ "庀":{"비": "N"},+ "広":{"광": "N"},+ "庄":{"장": "0N"},+ "庇":{"비": "0N"},+ "床":{"상": "0E"},+ "庋":{"기": "1N"},+ "序":{"서": "0E"},+ "底":{"저": "0E"},+ "庖":{"포": "1N"},+ "店":{"점": "0E"},+ "庚":{"경": "0E"},+ "府":{"부": "0E"},+ "庠":{"상": "0N"},+ "庥":{"휴": "N"},+ "度":{"도": "0E", "탁": "0N"},+ "座":{"좌": "0E"},+ "庨":{"효": "N"},+ "庫":{"고": "0E"},+ "庭":{"정": "0E"},+ "庳":{"비": "1N"},+ "庵":{"암": "0N"},+ "庶":{"서": "0E"},+ "康":{"강": "0E"},+ "庸":{"용": "0E"},+ "庽":{"우": "1N"},+ "庾":{"유": "0N"},+ "廁":{"측": "1N"},+ "廂":{"상": "0N"},+ "廈":{"하": "0N"},+ "廉":{"렴": "0E", "염": "0"},+ "廊":{"낭": "0", "랑": "0E"},+ "廋":{"수": "1N"},+ "廏":{"구": "N"},+ "廐":{"구": "0N"},+ "廑":{"근": "1N"},+ "廓":{"곽": "0N", "확": "0N"},+ "廕":{"음": "1N"},+ "廖":{"료": "0N"},+ "廙":{"이": "N"},+ "廚":{"주": "0N"},+ "廛":{"전": "0N"},+ "廝":{"시": "1N"},+ "廞":{"흠": "1N"},+ "廟":{"묘": "0E"},+ "廠":{"창": "0N"},+ "廡":{"무": "1N"},+ "廢":{"폐": "0E"},+ "廣":{"광": "0E"},+ "廥":{"괴": "1N"},+ "廧":{"장": "1N"},+ "廨":{"해": "1N"},+ "廩":{"름": "1N"},+ "廬":{"려": "0N", "여": "0"},+ "廱":{"옹": "1N"},+ "廳":{"청": "0E"},+ "延":{"연": "0E"},+ "廷":{"정": "0E"},+ "建":{"건": "0E"},+ "廻":{"회": "0N"},+ "廿":{"입": "1N"},+ "弁":{"변": "0N"},+ "弃":{"기": "1N"},+ "弄":{"농": "0", "롱": "0E"},+ "弇":{"감": "1N"},+ "弈":{"혁": "1N"},+ "弊":{"폐": "0E"},+ "弋":{"익": "1N"},+ "式":{"식": "0E"},+ "弑":{"시": "0"},+ "弒":{"시": "N"},+ "弓":{"궁": "0E"},+ "弔":{"조": "0E"},+ "引":{"인": "0E"},+ "弗":{"불": "0N"},+ "弘":{"홍": "0E"},+ "弛":{"이": "0N"},+ "弟":{"제": "0E"},+ "弢":{"도": "1N"},+ "弥":{"미": "1N"},+ "弦":{"현": "0N"},+ "弧":{"호": "0N"},+ "弩":{"노": "0N"},+ "弭":{"미": "1N"},+ "弱":{"약": "0E"},+ "弴":{"돈": "1N"},+ "張":{"장": "0E"},+ "強":{"강": "E"},+ "强":{"강": "0N"},+ "弼":{"필": "0N"},+ "彀":{"구": "1N"},+ "彆":{"별": "1N"},+ "彈":{"탄": "0E"},+ "彊":{"강": "0N"},+ "彌":{"미": "0N"},+ "彎":{"만": "0N"},+ "彔":{"록": "1N"},+ "彖":{"단": "0N"},+ "彗":{"세": "N", "혜": "0N"},+ "彘":{"체": "1N"},+ "彙":{"휘": "0N"},+ "彛":{"이": "0N"},+ "彝":{"이": "1N"},+ "形":{"형": "0E"},+ "彤":{"동": "1N"},+ "彥":{"언": "N"},+ "彦":{"언": "0N"},+ "彧":{"욱": "0N"},+ "彩":{"채": "0E"},+ "彪":{"표": "0N"},+ "彫":{"조": "0N"},+ "彬":{"빈": "0N"},+ "彭":{"팽": "0N"},+ "彰":{"창": "0N"},+ "影":{"영": "0E"},+ "彷":{"방": "0N"},+ "役":{"역": "0E"},+ "彼":{"피": "0E"},+ "彿":{"불": "0N"},+ "往":{"왕": "0E"},+ "征":{"정": "0E"},+ "徂":{"조": "1N"},+ "待":{"대": "0E"},+ "徇":{"순": "0N"},+ "很":{"흔": "1N"},+ "徉":{"양": "1N"},+ "徊":{"회": "0N"},+ "律":{"률": "0E", "율": "0"},+ "後":{"후": "0E"},+ "徐":{"서": "0E"},+ "徑":{"경": "0E"},+ "徒":{"도": "0E"},+ "得":{"득": "0E"},+ "徘":{"배": "0N"},+ "徙":{"사": "0N"},+ "徜":{"상": "1N"},+ "從":{"종": "0E"},+ "徠":{"래": "0N"},+ "御":{"어": "0E"},+ "徣":{"차": "1N"},+ "徧":{"편": "1N"},+ "徨":{"황": "0N"},+ "復":{"복": "0E", "부": "0N"},+ "循":{"순": "0E"},+ "徬":{"방": "1N"},+ "徭":{"요": "1N"},+ "微":{"미": "0E"},+ "徯":{"혜": "1N"},+ "徳":{"덕": "N"},+ "徵":{"징": "0E"},+ "德":{"덕": "0E"},+ "徹":{"철": "0E"},+ "徼":{"요": "1N"},+ "徽":{"휘": "0N"},+ "心":{"심": "0E"},+ "必":{"필": "0E"},+ "忈":{"인": "N"},+ "忉":{"도": "1N"},+ "忌":{"기": "0E"},+ "忍":{"인": "0E"},+ "忎":{"인": "N"},+ "忐":{"탐": "1N"},+ "忒":{"특": "1N"},+ "忓":{"간": "N", "한": "N"},+ "忕":{"세": "N"},+ "忖":{"촌": "0N"},+ "志":{"지": "0E"},+ "忘":{"망": "0E"},+ "忙":{"망": "0E"},+ "忝":{"첨": "1N"},+ "忞":{"민": "1N"},+ "忟":{"민": "1N"},+ "忠":{"충": "0E"},+ "忡":{"충": "1N"},+ "忤":{"오": "1N"},+ "忨":{"완": "1N"},+ "快":{"쾌": "0E"},+ "忭":{"변": "1N"},+ "忮":{"기": "1N"},+ "忯":{"기": "N", "지": "N"},+ "忱":{"침": "1N"},+ "念":{"념": "0E", "염": "0"},+ "忸":{"뉴": "1N"},+ "忻":{"흔": "1N"},+ "忼":{"강": "1N"},+ "忽":{"홀": "0E"},+ "忿":{"분": "0N"},+ "怊":{"초": "1N"},+ "怍":{"작": "1N"},+ "怏":{"앙": "0N"},+ "怒":{"노": "0E", "로": "0"},+ "怔":{"정": "1N"},+ "怕":{"파": "1N"},+ "怖":{"포": "0N"},+ "怗":{"첩": "1N"},+ "怙":{"호": "1N"},+ "怛":{"달": "1N"},+ "怜":{"령": "0N", "영": "0"},+ "思":{"사": "0E"},+ "怠":{"태": "0E"},+ "怡":{"이": "0N"},+ "急":{"급": "0E"},+ "怦":{"평": "1N"},+ "性":{"성": "0E"},+ "怨":{"원": "0E"},+ "怩":{"니": "1N"},+ "怪":{"괴": "0E"},+ "怯":{"겁": "0N"},+ "怰":{"현": "N"},+ "怳":{"황": "1N"},+ "恁":{"임": "0N"},+ "恂":{"순": "0N"},+ "恃":{"시": "0N"},+ "恆":{"항": "1N"},+ "恇":{"광": "1N"},+ "恈":{"모": "1N"},+ "恊":{"협": "1N"},+ "恍":{"황": "0N"},+ "恐":{"공": "0E"},+ "恒":{"항": "0E"},+ "恕":{"서": "0E"},+ "恙":{"양": "0N"},+ "恚":{"에": "1N"},+ "恝":{"괄": "0N"},+ "恟":{"흉": "1N"},+ "恠":{"괴": "1"},+ "恢":{"회": "0N"},+ "恣":{"자": "0E"},+ "恤":{"휼": "0N"},+ "恥":{"치": "0E"},+ "恨":{"한": "0E"},+ "恩":{"은": "0E"},+ "恪":{"각": "0N"},+ "恫":{"통": "1N"},+ "恬":{"념": "0N"},+ "恭":{"공": "0E"},+ "息":{"식": "0E"},+ "恰":{"흡": "0N"},+ "恵":{"혜": "N"},+ "悁":{"연": "1N"},+ "悃":{"곤": "1N"},+ "悄":{"초": "1N"},+ "悅":{"열": "0E"},+ "悆":{"서": "N", "여": "N"},+ "悉":{"실": "0N"},+ "悊":{"철": "N"},+ "悋":{"린": "1N"},+ "悌":{"제": "0N"},+ "悍":{"한": "0N"},+ "悏":{"협": "1N"},+ "悒":{"읍": "1N"},+ "悔":{"회": "0E"},+ "悕":{"희": "1N"},+ "悖":{"패": "0N"},+ "悗":{"문": "1N"},+ "悚":{"송": "0N"},+ "悛":{"전": "0N"},+ "悟":{"오": "0E"},+ "悠":{"유": "0E"},+ "悢":{"량": "1N"},+ "患":{"환": "0E"},+ "悤":{"총": "0N"},+ "悧":{"리": "0N"},+ "悰":{"종": "0N"},+ "悱":{"비": "1N"},+ "悲":{"비": "0E"},+ "悳":{"덕": "0N"},+ "悴":{"췌": "0N"},+ "悵":{"창": "1N"},+ "悶":{"민": "0N"},+ "悸":{"계": "0N"},+ "悻":{"행": "1N"},+ "悼":{"도": "0N"},+ "悽":{"처": "0N"},+ "悾":{"강": "N", "공": "1"},+ "惄":{"녁": "1N"},+ "情":{"정": "0E"},+ "惆":{"추": "1N"},+ "惇":{"돈": "0N"},+ "惉":{"첨": "1N"},+ "惋":{"완": "1N"},+ "惏":{"람": "1N"},+ "惑":{"혹": "0E"},+ "惓":{"권": "1N"},+ "惕":{"척": "1N"},+ "惗":{"녑": "N"},+ "惘":{"망": "1N"},+ "惙":{"철": "1N"},+ "惚":{"홀": "0N"},+ "惛":{"혼": "1"},+ "惜":{"석": "0E"},+ "惝":{"창": "1N"},+ "惞":{"흔": "N"},+ "惟":{"유": "0E"},+ "惠":{"혜": "0E"},+ "惡":{"악": "0E", "오": "0N"},+ "惢":{"쇄": "1"},+ "惰":{"타": "0N"},+ "惱":{"뇌": "0E"},+ "惲":{"운": "1N"},+ "想":{"상": "0E"},+ "惴":{"췌": "1N"},+ "惶":{"황": "0N"},+ "惷":{"준": "1N"},+ "惸":{"경": "1N"},+ "惹":{"야": "0N"},+ "惺":{"성": "0N"},+ "惻":{"측": "0N"},+ "惼":{"편": "1N"},+ "愀":{"초": "1N"},+ "愁":{"수": "0E"},+ "愃":{"선": "1N", "훤": "N"},+ "愆":{"건": "0N"},+ "愈":{"유": "0E"},+ "愉":{"유": "0N"},+ "愍":{"민": "0N"},+ "愎":{"퍅": "0N"},+ "意":{"의": "0E"},+ "愔":{"음": "1N"},+ "愕":{"악": "0N"},+ "愚":{"우": "0E"},+ "愛":{"애": "0E"},+ "愜":{"협": "1N"},+ "愞":{"난": "N"},+ "感":{"감": "0E"},+ "愢":{"시": "N"},+ "愧":{"괴": "0E"},+ "愨":{"각": "N"},+ "愫":{"소": "N"},+ "愬":{"소": "1N"},+ "愭":{"기": "1N"},+ "愰":{"황": "0N"},+ "愴":{"창": "0N"},+ "愷":{"개": "0N"},+ "愼":{"신": "0E"},+ "愾":{"개": "0N"},+ "愿":{"원": "0N"},+ "慂":{"용": "0N"},+ "慄":{"률": "0N", "율": "0"},+ "慆":{"도": "1N"},+ "慇":{"은": "0N"},+ "慈":{"자": "0E"},+ "慊":{"겸": "0N"},+ "態":{"태": "0E"},+ "慌":{"황": "0N"},+ "慍":{"온": "1N"},+ "慏":{"명": "N"},+ "慒":{"종": "1N"},+ "慓":{"표": "0N"},+ "慔":{"모": "N"},+ "慕":{"모": "0E"},+ "慘":{"참": "0E"},+ "慙":{"참": "0E"},+ "慚":{"참": "1N"},+ "慜":{"민": "N"},+ "慝":{"특": "0N"},+ "慟":{"통": "0N"},+ "慠":{"오": "1N"},+ "慡":{"상": "N"},+ "慢":{"만": "0E"},+ "慣":{"관": "0E"},+ "慤":{"각": "0N"},+ "慧":{"혜": "0E"},+ "慨":{"개": "0E"},+ "慪":{"우": "N"},+ "慫":{"종": "0N"},+ "慮":{"려": "0E"},+ "慰":{"위": "0E"},+ "慱":{"단": "1N"},+ "慳":{"간": "1N"},+ "慴":{"습": "1N"},+ "慵":{"용": "1N"},+ "慶":{"경": "0E"},+ "慷":{"강": "0N"},+ "慺":{"루": "1N"},+ "慼":{"척": "N"},+ "慽":{"척": "0N"},+ "慾":{"욕": "0E"},+ "憁":{"총": "0N"},+ "憂":{"우": "0E"},+ "憃":{"용": "1N"},+ "憊":{"비": "0N"},+ "憍":{"교": "1N"},+ "憎":{"증": "0E"},+ "憐":{"련": "0E", "연": "0"},+ "憑":{"빙": "0N"},+ "憒":{"궤": "1N"},+ "憓":{"혜": "N"},+ "憔":{"초": "0N"},+ "憖":{"은": "1N"},+ "憘":{"희": "0N"},+ "憙":{"희": "0N"},+ "憚":{"탄": "0N"},+ "憤":{"분": "0E"},+ "憧":{"동": "0N"},+ "憨":{"감": "1N"},+ "憩":{"게": "0N"},+ "憫":{"민": "0E"},+ "憬":{"경": "0N"},+ "憮":{"무": "0N"},+ "憯":{"참": "1N"},+ "憲":{"헌": "0E"},+ "憶":{"억": "0E"},+ "憸":{"섬": "1N"},+ "憺":{"담": "0N"},+ "憻":{"탄": "1N"},+ "憼":{"경": "1N"},+ "憽":{"송": "N"},+ "憾":{"감": "0N"},+ "懃":{"근": "0N"},+ "懆":{"조": "1N"},+ "懇":{"간": "0E"},+ "懈":{"해": "0N"},+ "應":{"응": "0E"},+ "懊":{"오": "0N"},+ "懋":{"무": "0N"},+ "懌":{"역": "1N"},+ "懏":{"준": "N"},+ "懕":{"염": "1N"},+ "懗":{"하": "1N"},+ "懞":{"몽": "1N"},+ "懟":{"대": "1N"},+ "懣":{"문": "1N"},+ "懦":{"나": "0N"},+ "懲":{"징": "0E"},+ "懶":{"나": "0", "라": "0N"},+ "懷":{"회": "0E"},+ "懸":{"현": "0E"},+ "懺":{"참": "0N"},+ "懼":{"구": "0E"},+ "懽":{"환": "1N"},+ "懾":{"섭": "1N"},+ "懿":{"의": "0N"},+ "戀":{"련": "0E", "연": "0"},+ "戇":{"당": "0N"},+ "戈":{"과": "0N"},+ "戊":{"무": "0E"},+ "戌":{"술": "0E"},+ "戍":{"수": "0N"},+ "戎":{"융": "0N"},+ "成":{"성": "0EN"},+ "我":{"아": "0E"},+ "戒":{"계": "0E"},+ "戔":{"잔": "1"},+ "戕":{"장": "1N"},+ "或":{"혹": "0E"},+ "戚":{"척": "0E"},+ "戞":{"알": "1"},+ "戟":{"극": "0N"},+ "戡":{"감": "0N"},+ "戢":{"집": "1N"},+ "戧":{"창": "1N"},+ "戩":{"전": "1N"},+ "截":{"절": "0N"},+ "戭":{"연": "N", "인": "N"},+ "戮":{"륙": "0N", "육": "0"},+ "戰":{"전": "0E"},+ "戱":{"희": "0N"},+ "戲":{"희": "1E"},+ "戳":{"착": "1N"},+ "戴":{"대": "0N"},+ "戵":{"구": "1N"},+ "戶":{"호": "0E"},+ "戹":{"액": "1N"},+ "戾":{"려": "0N"},+ "房":{"방": "0E"},+ "所":{"소": "0E"},+ "扁":{"편": "0N"},+ "扃":{"경": "1N"},+ "扇":{"선": "0N"},+ "扈":{"호": "0N"},+ "扉":{"비": "0N"},+ "扊":{"염": "1N"},+ "手":{"수": "0E"},+ "才":{"재": "0E"},+ "扎":{"찰": "1N"},+ "扑":{"복": "1N"},+ "扒":{"배": "1N"},+ "打":{"타": "0E"},+ "扗":{"재": "1N"},+ "托":{"탁": "0E"},+ "扛":{"강": "1N"},+ "扜":{"우": "N"},+ "扞":{"한": "N"},+ "扣":{"구": "1N"},+ "扨":{"인": "1"},+ "扮":{"분": "0N"},+ "扱":{"급": "0N"},+ "扳":{"반": "1N"},+ "扶":{"부": "0E"},+ "批":{"비": "0E"},+ "扺":{"지": "1N"},+ "扼":{"액": "0N"},+ "找":{"조": "1N"},+ "承":{"승": "0E"},+ "技":{"기": "0E"},+ "抃":{"변": "1N"},+ "抄":{"초": "0E"},+ "抆":{"문": "1N"},+ "抉":{"결": "0N"},+ "把":{"파": "0E"},+ "抏":{"완": "N"},+ "抑":{"억": "0E"},+ "抒":{"서": "0N"},+ "抔":{"부": "1N"},+ "投":{"투": "0E"},+ "抖":{"두": "1N"},+ "抗":{"항": "0E"},+ "折":{"절": "0E"},+ "抛":{"포": "0N"},+ "抦":{"병": "N"},+ "抨":{"평": "1N"},+ "披":{"피": "0N"},+ "抬":{"대": "N", "태": "1"},+ "抮":{"진": "N"},+ "抱":{"포": "0E"},+ "抲":{"하": "N"},+ "抵":{"저": "0E"},+ "抹":{"말": "0N"},+ "押":{"압": "0E"},+ "抽":{"추": "0E"},+ "拂":{"불": "0E"},+ "拄":{"주": "1N"},+ "担":{"단": "1N"},+ "拆":{"탁": "1N"},+ "拇":{"무": "0N"},+ "拈":{"념": "0N"},+ "拉":{"납": "0", "랍": "0N"},+ "拊":{"부": "1N"},+ "拋":{"포": "N"},+ "拌":{"반": "0N"},+ "拍":{"박": "0E"},+ "拏":{"나": "0N", "라": "0"},+ "拐":{"괴": "0N"},+ "拑":{"겸": "1N"},+ "拒":{"거": "0E"},+ "拓":{"척": "0E", "탁": "0N"},+ "拔":{"발": "0E"},+ "拕":{"타": "1N"},+ "拖":{"타": "0N"},+ "拗":{"요": "0N"},+ "拘":{"구": "0E"},+ "拙":{"졸": "0E"},+ "招":{"초": "0E"},+ "拜":{"배": "0E"},+ "括":{"괄": "0N"},+ "拭":{"식": "0N"},+ "拮":{"길": "0N"},+ "拯":{"증": "0N"},+ "拱":{"공": "0N"},+ "拳":{"권": "0E"},+ "拵":{"존": "1N"},+ "拶":{"찰": "1"},+ "拷":{"고": "0N"},+ "拽":{"예": "1N"},+ "拾":{"습": "0E", "십": "0N"},+ "拿":{"나": "0N"},+ "持":{"지": "0E"},+ "挂":{"괘": "1N"},+ "指":{"지": "0E"},+ "按":{"안": "0N"},+ "挌":{"격": "1N"},+ "挐":{"나": "1N"},+ "挑":{"도": "0E"},+ "挒":{"렬": "1N"},+ "挨":{"애": "1N"},+ "挪":{"나": "1N"},+ "挫":{"좌": "0N"},+ "振":{"진": "0E"},+ "挹":{"읍": "1N"},+ "挺":{"정": "0N"},+ "挻":{"연": "0N"},+ "挽":{"만": "0N"},+ "挾":{"협": "0N"},+ "捂":{"오": "1N"},+ "捃":{"군": "1N"},+ "捄":{"구": "1N"},+ "捆":{"곤": "1N"},+ "捉":{"착": "0E"},+ "捌":{"팔": "0N"},+ "捍":{"한": "1N"},+ "捎":{"소": "1N"},+ "捏":{"날": "0N"},+ "捐":{"연": "0N"},+ "捓":{"야": "N"},+ "捕":{"포": "0E"},+ "捗":{"척": "1N"},+ "捚":{"재": "N"},+ "捧":{"봉": "0N"},+ "捨":{"사": "0E"},+ "捩":{"렬": "1N"},+ "捫":{"문": "1N"},+ "据":{"거": "0N"},+ "捱":{"애": "1N"},+ "捲":{"권": "0N"},+ "捶":{"추": "1N"},+ "捷":{"첩": "0N"},+ "捺":{"날": "0N"},+ "捻":{"념": "0N", "염": "0"},+ "捿":{"서": "0N"},+ "掀":{"흔": "1N"},+ "掃":{"소": "0E"},+ "掄":{"륜": "1N"},+ "掇":{"철": "1N"},+ "授":{"수": "0E"},+ "掉":{"도": "0N"},+ "掊":{"부": "1N"},+ "掌":{"장": "0E"},+ "掎":{"기": "1N"},+ "掏":{"도": "1N"},+ "排":{"배": "0E"},+ "掖":{"액": "0N"},+ "掘":{"굴": "0N"},+ "掛":{"괘": "0E"},+ "掜":{"예": "1N"},+ "掟":{"정": "1N"},+ "掠":{"략": "0E", "약": "0"},+ "採":{"채": "0E"},+ "探":{"탐": "0E"},+ "接":{"접": "0E"},+ "控":{"공": "0N"},+ "推":{"추": "0E"},+ "掩":{"엄": "0N"},+ "措":{"조": "0N"},+ "掬":{"국": "1N"},+ "掾":{"연": "1N"},+ "揀":{"간": "0N"},+ "揃":{"전": "1N"},+ "揄":{"유": "0N"},+ "揆":{"규": "0N"},+ "揉":{"유": "1N"},+ "描":{"묘": "0N"},+ "提":{"제": "0E"},+ "插":{"삽": "N"},+ "揖":{"읍": "0N"},+ "揚":{"양": "0E"},+ "換":{"환": "0E"},+ "揟":{"서": "1N"},+ "揠":{"알": "1N"},+ "握":{"악": "0N"},+ "揣":{"췌": "1N"},+ "揩":{"개": "1N"},+ "揫":{"추": "1N"},+ "揭":{"게": "0N"},+ "揮":{"휘": "0E"},+ "揲":{"설": "1N"},+ "援":{"원": "0E"},+ "揵":{"건": "1N"},+ "揶":{"야": "0N"},+ "揷":{"삽": "0N"},+ "搆":{"구": "1N"},+ "搉":{"각": "1N"},+ "損":{"손": "0E"},+ "搏":{"박": "0"},+ "搒":{"방": "1N"},+ "搔":{"소": "0N"},+ "搖":{"요": "0E"},+ "搗":{"도": "0N"},+ "搘":{"지": "N"},+ "搜":{"수": "0E"},+ "搠":{"삭": "N"},+ "搢":{"진": "0N"},+ "搤":{"액": "1N"},+ "搥":{"추": "1N"},+ "搨":{"탑": "1N"},+ "搪":{"당": "1N"},+ "搫":{"반": "1N"},+ "搬":{"반": "0N"},+ "搭":{"탑": "0"},+ "搯":{"도": "1N"},+ "搰":{"골": "1N"},+ "搴":{"건": "N"},+ "搶":{"창": "1N"},+ "携":{"휴": "0E"},+ "搾":{"착": "0N"},+ "摘":{"적": "0E"},+ "摛":{"리": "N"},+ "摞":{"라": "N"},+ "摠":{"총": "0N"},+ "摧":{"최": "1N"},+ "摩":{"마": "0N"},+ "摭":{"척": "1N"},+ "摯":{"지": "0N"},+ "摳":{"구": "1N"},+ "摸":{"모": "0N"},+ "摹":{"모": "0N"},+ "摺":{"접": "0N"},+ "摻":{"섬": "1N"},+ "摽":{"표": "1N"},+ "撅":{"궤": "1N"},+ "撈":{"로": "0N"},+ "撐":{"탱": "1N"},+ "撑":{"탱": "0N"},+ "撒":{"살": "0N"},+ "撓":{"뇨": "N", "요": "0"},+ "撕":{"서": "1N"},+ "撙":{"준": "1N"},+ "撚":{"년": "0N", "연": "0"},+ "撛":{"린": "N"},+ "撝":{"휘": "1N"},+ "撞":{"당": "0N"},+ "撟":{"교": "1N"},+ "撤":{"철": "0N"},+ "撥":{"발": "0N"},+ "撩":{"료": "1N"},+ "撫":{"무": "0N"},+ "播":{"파": "0E"},+ "撮":{"촬": "0N"},+ "撰":{"찬": "0N"},+ "撲":{"박": "0N"},+ "撻":{"달": "0N"},+ "撼":{"감": "1N"},+ "撾":{"과": "1N"},+ "撿":{"검": "1N"},+ "擁":{"옹": "0E"},+ "擄":{"노": "0", "로": "0N"},+ "擅":{"천": "0N"},+ "擇":{"택": "0E"},+ "擉":{"착": "1N"},+ "擊":{"격": "0E"},+ "操":{"조": "0E"},+ "擎":{"경": "0N"},+ "擐":{"환": "1N"},+ "擒":{"금": "0N"},+ "擔":{"담": "0E"},+ "擕":{"휴": "1"},+ "擗":{"벽": "1N"},+ "擘":{"벽": "0N"},+ "據":{"거": "0E"},+ "擠":{"제": "1N"},+ "擡":{"대": "0N"},+ "擢":{"탁": "0N"},+ "擣":{"도": "1N"},+ "擥":{"람": "0N"},+ "擦":{"찰": "0N"},+ "擧":{"거": "0E"},+ "擬":{"의": "0N"},+ "擭":{"화": "1"},+ "擯":{"빈": "1N"},+ "擱":{"각": "1N"},+ "擲":{"척": "0N"},+ "擴":{"확": "0E"},+ "擺":{"파": "0N"},+ "擾":{"요": "0N"},+ "攀":{"반": "0N"},+ "攂":{"뢰": "1N"},+ "攄":{"터": "0N"},+ "攇":{"헌": "1N"},+ "攊":{"력": "1N"},+ "攏":{"롱": "1N"},+ "攔":{"란": "1N"},+ "攘":{"양": "0N"},+ "攙":{"참": "1N"},+ "攝":{"섭": "0E"},+ "攢":{"찬": "1N"},+ "攣":{"련": "0N"},+ "攤":{"탄": "1N"},+ "攪":{"교": "0N"},+ "攫":{"확": "0N"},+ "攬":{"람": "0N"},+ "支":{"지": "0E"},+ "攲":{"기": "1N"},+ "收":{"수": "0E"},+ "攷":{"고": "0N"},+ "攸":{"유": "0N"},+ "改":{"개": "0E"},+ "攻":{"공": "0E"},+ "攽":{"반": "1N"},+ "放":{"방": "0E"},+ "政":{"정": "0E"},+ "敃":{"민": "N"},+ "故":{"고": "0E"},+ "效":{"효": "0E"},+ "敉":{"미": "1N"},+ "敍":{"서": "0E"},+ "敎":{"교": "0E"},+ "敏":{"민": "0E"},+ "救":{"구": "0E"},+ "敒":{"진": "N"},+ "敔":{"어": "1N"},+ "敕":{"칙": "1N"},+ "敖":{"오": "0N"},+ "敗":{"패": "0E"},+ "敘":{"서": "N"},+ "教":{"교": "N"},+ "敝":{"폐": "1N"},+ "敞":{"창": "0N"},+ "敢":{"감": "0E"},+ "散":{"산": "0E"},+ "敦":{"돈": "0E"},+ "敬":{"경": "0E"},+ "敭":{"양": "0N"},+ "敲":{"고": "0N"},+ "整":{"정": "0E"},+ "敵":{"적": "0E"},+ "敷":{"부": "0N"},+ "數":{"삭": "0N", "수": "0E"},+ "敾":{"선": "0N"},+ "斁":{"두": "1N"},+ "斂":{"렴": "0N"},+ "斃":{"폐": "0N"},+ "斅":{"효": "0N"},+ "文":{"문": "0E"},+ "斌":{"빈": "0N"},+ "斐":{"비": "0N"},+ "斑":{"반": "0N"},+ "斗":{"두": "0E"},+ "料":{"료": "0E", "요": "0"},+ "斛":{"곡": "0N"},+ "斜":{"사": "0E"},+ "斝":{"가": "1N"},+ "斟":{"짐": "0N"},+ "斡":{"알": "0N"},+ "斤":{"근": "0E"},+ "斥":{"척": "0E"},+ "斧":{"부": "0N"},+ "斫":{"작": "0N"},+ "斬":{"참": "0N"},+ "斯":{"사": "0E"},+ "新":{"신": "0E"},+ "斱":{"작": "1N"},+ "斲":{"착": "1N"},+ "斷":{"단": "0E"},+ "方":{"방": "0E"},+ "於":{"어": "0E"},+ "施":{"시": "0E"},+ "斿":{"유": "1"},+ "旁":{"방": "0N"},+ "旂":{"기": "1N"},+ "旃":{"전": "1N"},+ "旄":{"모": "1N"},+ "旅":{"려": "0E", "여": "0"},+ "旆":{"패": "1N"},+ "旊":{"방": "1N"},+ "旋":{"선": "0E"},+ "旌":{"정": "0N"},+ "族":{"족": "0E"},+ "旒":{"류": "0N"},+ "旗":{"기": "0E"},+ "无":{"무": "0N"},+ "旣":{"기": "0E"},+ "日":{"일": "0E"},+ "旦":{"단": "0E"},+ "旨":{"지": "0N"},+ "早":{"조": "0E"},+ "旬":{"순": "0E"},+ "旭":{"욱": "0N"},+ "旱":{"한": "0E"},+ "旲":{"대": "1N"},+ "旴":{"우": "0N"},+ "旺":{"왕": "0N"},+ "旻":{"민": "0N"},+ "旼":{"민": "0N"},+ "旽":{"돈": "0N"},+ "旿":{"오": "0N"},+ "昀":{"윤": "1N"},+ "昂":{"앙": "N"},+ "昃":{"측": "1N"},+ "昆":{"곤": "0N"},+ "昇":{"승": "0E"},+ "昉":{"방": "0N"},+ "昊":{"호": "0N"},+ "昌":{"창": "0E"},+ "昍":{"헌": "N", "훤": "N"},+ "明":{"명": "0E"},+ "昏":{"혼": "0E"},+ "昐":{"분": "0N"},+ "昑":{"금": "0N"},+ "易":{"역": "0E", "이": "0N"},+ "昔":{"석": "0E"},+ "昕":{"흔": "0N"},+ "昛":{"거": "1N"},+ "昜":{"양": "N"},+ "昞":{"병": "0N"},+ "星":{"성": "0E"},+ "映":{"영": "0E"},+ "昡":{"현": "1N"},+ "昣":{"진": "N"},+ "昤":{"령": "1N"},+ "春":{"춘": "0E"},+ "昧":{"매": "0N"},+ "昨":{"작": "0E"},+ "昫":{"구": "1N"},+ "昭":{"소": "0E", "조": "N"},+ "是":{"시": "0E"},+ "昰":{"하": "0N"},+ "昱":{"욱": "0N"},+ "昴":{"묘": "0N"},+ "昵":{"닐": "1N"},+ "昶":{"창": "0N"},+ "昷":{"온": "1N"},+ "昺":{"병": "0N"},+ "昻":{"앙": "0N"},+ "晁":{"조": "0N"},+ "時":{"시": "0E"},+ "晃":{"황": "0N"},+ "晄":{"황": "0N"},+ "晈":{"교": "1N"},+ "晉":{"진": "0N"},+ "晋":{"진": "0N"},+ "晌":{"상": "1N"},+ "晎":{"홍": "1N"},+ "晏":{"안": "0N"},+ "晐":{"해": "N"},+ "晑":{"향": "N"},+ "晙":{"준": "0N"},+ "晚":{"만": "E"},+ "晛":{"현": "0N"},+ "晝":{"주": "0E"},+ "晞":{"희": "0N"},+ "晟":{"성": "0N"},+ "晠":{"성": "N"},+ "晡":{"포": "1N"},+ "晢":{"절": "1N", "제": "N"},+ "晤":{"오": "0N"},+ "晥":{"환": "0N"},+ "晦":{"회": "0N"},+ "晧":{"호": "0N"},+ "晨":{"신": "0E"},+ "晩":{"만": "0"},+ "晫":{"탁": "0N"},+ "晬":{"수": "1N"},+ "晭":{"주": "N"},+ "普":{"보": "0E"},+ "景":{"경": "0E"},+ "晰":{"석": "1N"},+ "晳":{"석": "0N"},+ "晴":{"청": "0EN"},+ "晶":{"정": "0N"},+ "晷":{"귀": "0N"},+ "晸":{"정": "0N"},+ "晹":{"역": "N"},+ "智":{"지": "0E"},+ "晻":{"암": "1N"},+ "晽":{"림": "N"},+ "晿":{"창": "N"},+ "暄":{"훤": "0N"},+ "暇":{"가": "0E"},+ "暈":{"운": "0N", "훈": "0N"},+ "暉":{"휘": "0N"},+ "暋":{"민": "1N"},+ "暌":{"규": "1N"},+ "暎":{"영": "0N"},+ "暐":{"위": "0N"},+ "暑":{"서": "0E"},+ "暖":{"난": "0E"},+ "暗":{"암": "0E"},+ "暘":{"양": "0N"},+ "暚":{"요": "N"},+ "暝":{"명": "0N"},+ "暞":{"교": "1N"},+ "暠":{"고": "0N"},+ "暢":{"창": "0E"},+ "暣":{"기": "1N"},+ "暫":{"잠": "0E"},+ "暬":{"설": "1N"},+ "暮":{"모": "0E"},+ "暱":{"닐": "1N"},+ "暲":{"장": "0N"},+ "暳":{"혜": "0N"},+ "暴":{"포": "0N", "폭": "0E"},+ "暵":{"한": "1N"},+ "暸":{"료": "1N"},+ "暹":{"섬": "0N"},+ "暺":{"탄": "N"},+ "暻":{"경": "0N"},+ "暾":{"돈": "0N"},+ "暿":{"희": "1N"},+ "曀":{"에": "1N"},+ "曁":{"기": "1N"},+ "曄":{"엽": "0N"},+ "曅":{"엽": "1N"},+ "曆":{"력": "0E", "역": "0"},+ "曇":{"담": "0N"},+ "曈":{"동": "N"},+ "曉":{"효": "0E"},+ "曓":{"포": "1N"},+ "曔":{"경": "N"},+ "曖":{"애": "0N"},+ "曘":{"유": "N"},+ "曙":{"서": "0N"},+ "曚":{"몽": "1N"},+ "曛":{"훈": "1N"},+ "曜":{"요": "0N"},+ "曝":{"폭": "0N"},+ "曞":{"려": "N"},+ "曠":{"광": "0N"},+ "曣":{"연": "1N"},+ "曦":{"희": "0N"},+ "曨":{"롱": "1N"},+ "曩":{"낭": "1N"},+ "曪":{"라": "1N"},+ "曬":{"쇄": "1N"},+ "曮":{"엄": "1N"},+ "曯":{"촉": "1N"},+ "曰":{"왈": "0E"},+ "曲":{"곡": "0E"},+ "曳":{"예": "0N"},+ "更":{"갱": "0E", "경": "0N"},+ "曷":{"갈": "0N"},+ "書":{"서": "0E"},+ "曹":{"조": "0N"},+ "曺":{"조": "0N"},+ "曼":{"만": "0N"},+ "曾":{"증": "0E"},+ "替":{"체": "0E"},+ "最":{"최": "0E"},+ "會":{"회": "0E"},+ "朄":{"인": "N"},+ "朅":{"걸": "1N"},+ "月":{"월": "0E"},+ "有":{"유": "0E"},+ "朊":{"원": "N"},+ "朋":{"붕": "0E"},+ "朌":{"반": "1N"},+ "服":{"복": "0E"},+ "朔":{"삭": "0E"},+ "朕":{"짐": "0N"},+ "朗":{"낭": "0", "랑": "0N"},+ "望":{"망": "0E"},+ "朝":{"조": "0E"},+ "朞":{"기": "0N"},+ "期":{"기": "0E"},+ "朠":{"영": "N"},+ "朢":{"망": "N"},+ "朣":{"동": "1N"},+ "朦":{"몽": "0N"},+ "朧":{"롱": "0N"},+ "木":{"목": "0E"},+ "未":{"미": "0E"},+ "末":{"말": "0E"},+ "本":{"본": "0E"},+ "札":{"찰": "0N"},+ "朮":{"출": "0N"},+ "朱":{"주": "0E"},+ "朳":{"팔": "1N"},+ "朴":{"박": "0E"},+ "朶":{"타": "0N"},+ "机":{"궤": "0N"},+ "朽":{"후": "0N"},+ "朾":{"정": "N"},+ "杅":{"우": "1N"},+ "杆":{"간": "0N"},+ "杉":{"삼": "0N"},+ "杋":{"범": "N"},+ "杌":{"올": "N"},+ "李":{"리": "0E", "이": "0"},+ "杏":{"행": "0N"},+ "材":{"재": "0E"},+ "村":{"촌": "0E"},+ "杓":{"표": "0N"},+ "杖":{"장": "0N"},+ "杜":{"두": "0N"},+ "杝":{"이": "N"},+ "杞":{"기": "0N"},+ "束":{"속": "0E"},+ "杠":{"강": "1N"},+ "来":{"래": "N"},+ "杪":{"초": "1N"},+ "杬":{"완": "N", "원": "1N"},+ "杭":{"항": "0N"},+ "杯":{"배": "0E"},+ "杰":{"걸": "0N"},+ "東":{"동": "0E"},+ "杲":{"고": "1N"},+ "杳":{"묘": "0N"},+ "杵":{"저": "0N"},+ "杷":{"파": "0N"},+ "杻":{"뉴": "0N", "유": "0"},+ "杼":{"저": "1N"},+ "松":{"송": "0E"},+ "板":{"판": "0E"},+ "枃":{"진": "N"},+ "枇":{"비": "0N"},+ "枉":{"왕": "0N"},+ "枋":{"방": "0N"},+ "枌":{"분": "1N"},+ "枏":{"남": "0N"},+ "析":{"석": "0E"},+ "枒":{"아": "N"},+ "枓":{"두": "0N"},+ "枕":{"침": "0E"},+ "林":{"림": "0E", "임": "0"},+ "枘":{"예": "1N"},+ "枙":{"와": "1N"},+ "枚":{"매": "0N"},+ "果":{"과": "0E"},+ "枝":{"지": "0E"},+ "枯":{"고": "0E"},+ "枰":{"평": "0N"},+ "枲":{"시": "1N"},+ "枳":{"지": "0N"},+ "架":{"가": "0E"},+ "枷":{"가": "0N"},+ "枸":{"구": "0N"},+ "枾":{"시": "0N"},+ "柁":{"타": "1N"},+ "柄":{"병": "0N"},+ "柅":{"니": "1N"},+ "柊":{"종": "1N"},+ "柏":{"백": "0N"},+ "某":{"모": "0E"},+ "柑":{"감": "0N"},+ "柒":{"칠": "0N"},+ "染":{"염": "0E"},+ "柔":{"유": "0E"},+ "柖":{"소": "N"},+ "柗":{"송": "1"},+ "柘":{"자": "1N"},+ "柙":{"합": "1N"},+ "柚":{"유": "0N"},+ "柝":{"탁": "0N"},+ "柞":{"작": "1N"},+ "柟":{"남": "1"},+ "柢":{"저": "1N"},+ "柩":{"구": "0N"},+ "柬":{"간": "0N"},+ "柯":{"가": "0N"},+ "柰":{"나": "N", "내": "0N"},+ "柱":{"주": "0E"},+ "柳":{"류": "0E", "유": "0"},+ "柴":{"시": "0N"},+ "柵":{"책": "0N"},+ "柶":{"사": "0N"},+ "柹":{"시": "1N"},+ "査":{"사": "0E"},+ "柾":{"정": "0N"},+ "柿":{"시": "N"},+ "栃":{"회": "1"},+ "栄":{"영": "N"},+ "栐":{"영": "N"},+ "栒":{"순": "0N"},+ "栓":{"전": "0N"},+ "栖":{"서": "0N"},+ "栗":{"률": "0E", "율": "0"},+ "栝":{"괄": "1N"},+ "栞":{"간": "1N"},+ "校":{"교": "0E"},+ "栢":{"백": "0N"},+ "株":{"주": "0E"},+ "栮":{"이": "1N"},+ "栯":{"욱": "0N"},+ "栱":{"공": "1N"},+ "栲":{"고": "1N"},+ "栴":{"전": "1N"},+ "核":{"핵": "0E"},+ "根":{"근": "0E"},+ "栻":{"식": "1N"},+ "格":{"격": "0E"},+ "栽":{"재": "0E"},+ "桀":{"걸": "0N"},+ "桁":{"항": "0N"},+ "桂":{"계": "0E"},+ "桃":{"도": "0E"},+ "桄":{"광": "1N"},+ "框":{"광": "1N"},+ "案":{"안": "0E"},+ "桉":{"안": "1N"},+ "桎":{"질": "0N"},+ "桐":{"동": "0N"},+ "桑":{"상": "0E"},+ "桓":{"환": "0N"},+ "桔":{"길": "0N"},+ "桭":{"진": "0N"},+ "桯":{"정": "1N"},+ "桴":{"부": "1N"},+ "桶":{"통": "0N"},+ "桷":{"각": "1N"},+ "桾":{"군": "1N"},+ "桿":{"간": "0N"},+ "梁":{"량": "0E", "양": "0"},+ "梃":{"정": "1N"},+ "梅":{"매": "0E"},+ "梆":{"방": "1N"},+ "梏":{"곡": "0N"},+ "梓":{"재": "0N"},+ "梔":{"치": "0N"},+ "梗":{"경": "0N"},+ "梛":{"나": "1N"},+ "條":{"조": "0E"},+ "梟":{"효": "0N"},+ "梠":{"려": "1N"},+ "梡":{"관": "N", "완": "0N"},+ "梢":{"초": "0N"},+ "梣":{"심": "1"},+ "梧":{"오": "0N"},+ "梨":{"리": "0E", "이": "0"},+ "梭":{"사": "0N"},+ "梯":{"제": "0N"},+ "械":{"계": "0E"},+ "梱":{"곤": "0N"},+ "梳":{"소": "0N"},+ "梵":{"범": "0N"},+ "梶":{"미": "0N"},+ "棄":{"기": "0E"},+ "棅":{"병": "0N"},+ "棉":{"면": "0N"},+ "棊":{"기": "1N"},+ "棋":{"기": "0N"},+ "棌":{"채": "1N"},+ "棍":{"곤": "0N"},+ "棐":{"비": "1N"},+ "棒":{"봉": "0N"},+ "棕":{"종": "0N"},+ "棖":{"정": "1N"},+ "棗":{"조": "0N"},+ "棘":{"극": "0N"},+ "棚":{"붕": "0N"},+ "棟":{"동": "0N"},+ "棠":{"당": "0N"},+ "棣":{"체": "1N"},+ "棧":{"잔": "0N"},+ "棨":{"계": "0N"},+ "棬":{"권": "1N"},+ "森":{"삼": "0N"},+ "棲":{"서": "0N"},+ "棹":{"도": "0N"},+ "棺":{"관": "0N"},+ "棻":{"분": "1N"},+ "棼":{"분": "1N"},+ "棽":{"림": "N", "침": "N"},+ "椀":{"완": "0N"},+ "椁":{"곽": "1N"},+ "椄":{"접": "1N"},+ "椅":{"의": "0N"},+ "椆":{"주": "N"},+ "椋":{"량": "1", "양": "N"},+ "植":{"식": "0E"},+ "椎":{"추": "0N"},+ "椏":{"아": "N"},+ "椑":{"비": "1N"},+ "椒":{"초": "0N"},+ "椙":{"창": "1"},+ "椧":{"명": "0N"},+ "椰":{"야": "0N"},+ "椴":{"단": "1N"},+ "椶":{"종": "1N"},+ "椹":{"침": "1N"},+ "椽":{"연": "0N"},+ "椿":{"춘": "0N"},+ "楂":{"사": "1N"},+ "楊":{"양": "0E"},+ "楏":{"규": "1N"},+ "楓":{"풍": "0N"},+ "楔":{"설": "0N"},+ "楕":{"타": "0N"},+ "楗":{"건": "0N"},+ "楙":{"무": "0N"},+ "楚":{"초": "0N"},+ "楝":{"련": "1N"},+ "楞":{"릉": "0N"},+ "楠":{"남": "0N"},+ "楡":{"유": "0N"},+ "楢":{"유": "0N"},+ "楣":{"미": "0N"},+ "楥":{"원": "1N"},+ "楨":{"정": "0N"},+ "楪":{"접": "1N"},+ "楫":{"즙": "0N", "집": "N"},+ "楬":{"갈": "1N"},+ "業":{"업": "0E"},+ "楮":{"저": "0N"},+ "楯":{"순": "0N"},+ "楳":{"매": "1N"},+ "極":{"극": "0E"},+ "楷":{"해": "0N"},+ "楸":{"추": "0N"},+ "楹":{"영": "0N"},+ "楻":{"황": "N"},+ "榎":{"가": "1N"},+ "榑":{"부": "1N"},+ "榔":{"랑": "1N"},+ "榕":{"용": "0N"},+ "榘":{"구": "1N"},+ "榛":{"진": "0N"},+ "榜":{"방": "0N"},+ "榟":{"재": "1N"},+ "榤":{"걸": "1N"},+ "榥":{"황": "0N"},+ "榦":{"간": "1N"},+ "榧":{"비": "0N"},+ "榭":{"사": "1N"},+ "榮":{"영": "0E"},+ "榰":{"지": "1N"},+ "榱":{"최": "1N"},+ "榲":{"온": "N"},+ "榴":{"류": "0N"},+ "榷":{"교": "1N"},+ "榺":{"승": "N"},+ "榻":{"탑": "0N"},+ "榼":{"합": "1N"},+ "榾":{"골": "1N"},+ "榿":{"기": "N"},+ "槀":{"고": "1N"},+ "槁":{"고": "0N"},+ "槃":{"반": "0N"},+ "槇":{"전": "1", "진": "N"},+ "槊":{"삭": "1N"},+ "構":{"구": "0E"},+ "槌":{"퇴": "0N"},+ "槍":{"창": "0N"},+ "槎":{"차": "1N"},+ "槏":{"겸": "N"},+ "槐":{"괴": "0N"},+ "槓":{"공": "1N"},+ "槖":{"탁": "N"},+ "槢":{"습": "N"},+ "槥":{"혜": "1N"},+ "槦":{"용": "1N"},+ "槧":{"참": "1N"},+ "槨":{"곽": "0N"},+ "槩":{"개": "1N"},+ "槪":{"개": "0E"},+ "槭":{"색": "1N"},+ "槲":{"곡": "1N"},+ "槹":{"고": "1"},+ "槻":{"규": "0N"},+ "槽":{"조": "0N"},+ "槿":{"근": "0N"},+ "樀":{"적": "1N"},+ "樂":{"낙": "0", "락": "0E", "악": "0N", "요": "0N"},+ "樅":{"종": "1N"},+ "樊":{"번": "0N"},+ "樋":{"통": "1N"},+ "樑":{"량": "0N"},+ "樒":{"밀": "1N"},+ "樓":{"누": "0", "루": "0E"},+ "樔":{"소": "1N"},+ "樗":{"저": "0N"},+ "標":{"표": "0E"},+ "樛":{"규": "1N"},+ "樞":{"추": "0N"},+ "樟":{"장": "0N"},+ "模":{"모": "0E"},+ "樣":{"상": "N", "양": "0E"},+ "権":{"권": "N"},+ "樫":{"견": "1"},+ "樵":{"초": "0N"},+ "樸":{"박": "0N"},+ "樹":{"수": "0E"},+ "樺":{"화": "0N"},+ "樻":{"궤": "1N"},+ "樽":{"준": "0N"},+ "橃":{"벌": "1N"},+ "橄":{"감": "0N"},+ "橅":{"모": "N", "무": "N"},+ "橇":{"취": "1N"},+ "橈":{"요": "0N"},+ "橉":{"린": "N"},+ "橊":{"류": "1N"},+ "橋":{"교": "0E"},+ "橌":{"한": "N"},+ "橍":{"윤": "N"},+ "橐":{"탁": "1N"},+ "橒":{"운": "0N"},+ "橓":{"순": "0N"},+ "橘":{"귤": "0N"},+ "橙":{"등": "0N"},+ "橚":{"숙": "1N"},+ "機":{"기": "0E"},+ "橡":{"상": "0N"},+ "橢":{"타": "1N"},+ "橤":{"예": "N"},+ "橦":{"동": "1N"},+ "橫":{"횡": "0E"},+ "橲":{"희": "N"},+ "橵":{"산": "1N"},+ "橿":{"강": "1N"},+ "檀":{"단": "0E"},+ "檃":{"은": "N"},+ "檄":{"격": "0N"},+ "檉":{"정": "0N"},+ "檍":{"억": "0N"},+ "檎":{"금": "0N"},+ "檐":{"첨": "1N"},+ "檔":{"당": "1N"},+ "檗":{"벽": "0N"},+ "檜":{"회": "0N"},+ "檝":{"즙": "1N"},+ "檟":{"가": "1N"},+ "檠":{"경": "1N"},+ "檢":{"검": "0E"},+ "檣":{"장": "0N"},+ "檮":{"도": "1N"},+ "檳":{"빈": "0N"},+ "檶":{"염": "1"},+ "檻":{"함": "0N"},+ "檼":{"은": "1N"},+ "檿":{"염": "1N"},+ "櫂":{"도": "0N"},+ "櫃":{"궤": "0N"},+ "櫓":{"노": "0", "로": "0N"},+ "櫚":{"려": "0N"},+ "櫛":{"즐": "0N"},+ "櫜":{"고": "1N"},+ "櫝":{"독": "1N"},+ "櫞":{"연": "1N"},+ "櫟":{"력": "1N"},+ "櫨":{"로": "N"},+ "櫪":{"력": "1N"},+ "櫬":{"친": "1N"},+ "櫶":{"헌": "0N"},+ "櫻":{"앵": "0N"},+ "櫼":{"첨": "1N"},+ "欂":{"박": "1N"},+ "欃":{"참": "1N"},+ "欄":{"난": "0", "란": "0E"},+ "權":{"권": "0E"},+ "欌":{"장": "0N"},+ "欑":{"찬": "1N"},+ "欒":{"란": "0N"},+ "欖":{"람": "0N"},+ "欞":{"령": "1N"},+ "欠":{"흠": "0N"},+ "次":{"차": "0E"},+ "欣":{"흔": "0N"},+ "欬":{"해": "1N"},+ "欲":{"욕": "0E"},+ "欷":{"희": "1N"},+ "欸":{"애": "1N"},+ "欹":{"의": "1N"},+ "欺":{"기": "0E"},+ "欻":{"훌": "1N"},+ "欽":{"흠": "0N"},+ "款":{"관": "0N"},+ "欿":{"감": "1N"},+ "歃":{"삽": "1N"},+ "歆":{"흠": "0N"},+ "歇":{"헐": "0N"},+ "歉":{"겸": "1N"},+ "歊":{"효": "N"},+ "歌":{"가": "0E"},+ "歎":{"탄": "0E"},+ "歐":{"구": "0N"},+ "歔":{"허": "1N"},+ "歙":{"흡": "1N"},+ "歚":{"선": "1N"},+ "歛":{"감": "1N"},+ "歟":{"여": "0N"},+ "歠":{"철": "1N"},+ "歡":{"환": "0E"},+ "止":{"지": "0E"},+ "正":{"정": "0E"},+ "此":{"차": "0E"},+ "步":{"보": "0E"},+ "武":{"무": "0E"},+ "歧":{"기": "1N"},+ "歩":{"보": "N"},+ "歪":{"왜": "0N"},+ "歲":{"세": "0E"},+ "歷":{"력": "0E", "역": "0"},+ "歸":{"귀": "0E"},+ "死":{"사": "0E"},+ "歿":{"몰": "0N"},+ "殀":{"요": "1N"},+ "殂":{"조": "1N"},+ "殃":{"앙": "0E"},+ "殄":{"진": "0N"},+ "殆":{"태": "0E"},+ "殉":{"순": "0E"},+ "殊":{"수": "0E"},+ "殍":{"표": "1N"},+ "殑":{"긍": "1N"},+ "殖":{"식": "0N"},+ "殘":{"잔": "0E"},+ "殞":{"운": "0N"},+ "殢":{"체": "1N"},+ "殤":{"상": "1N"},+ "殫":{"탄": "1N"},+ "殭":{"강": "1N"},+ "殮":{"렴": "0N", "염": "0"},+ "殯":{"빈": "0N"},+ "殲":{"섬": "0N"},+ "殳":{"수": "1N"},+ "段":{"단": "0E"},+ "殷":{"은": "0N"},+ "殺":{"살": "0E", "쇄": "0N"},+ "殼":{"각": "0N"},+ "殽":{"효": "1N"},+ "殿":{"전": "0E"},+ "毀":{"훼": "N"},+ "毁":{"훼": "0E"},+ "毄":{"격": "1N"},+ "毅":{"의": "0N"},+ "毆":{"구": "0N"},+ "毋":{"무": "0N"},+ "母":{"모": "0E"},+ "每":{"매": "0E"},+ "毒":{"독": "0E"},+ "毓":{"육": "0N"},+ "比":{"비": "0E"},+ "毖":{"비": "0N"},+ "毗":{"비": "0N"},+ "毘":{"비": "0N"},+ "毚":{"참": "1N"},+ "毛":{"모": "0E"},+ "毫":{"호": "0E"},+ "毬":{"구": "0N"},+ "毯":{"담": "1N"},+ "毳":{"취": "1N"},+ "毸":{"시": "N"},+ "毿":{"산": "1"},+ "氅":{"창": "1N"},+ "氈":{"전": "0N"},+ "氏":{"씨": "0E"},+ "氐":{"저": "1N"},+ "民":{"민": "0E"},+ "氓":{"맹": "0N"},+ "氛":{"분": "1N"},+ "氣":{"기": "0E"},+ "氤":{"인": "1N"},+ "氳":{"온": "1N"},+ "水":{"수": "0E"},+ "氶":{"승": "N"},+ "氷":{"빙": "0E"},+ "永":{"영": "0E"},+ "氾":{"범": "0N"},+ "氿":{"궤": "1N"},+ "汀":{"정": "0N"},+ "汁":{"즙": "0N"},+ "求":{"구": "0E"},+ "汃":{"팔": "1N"},+ "汋":{"작": "1N"},+ "汎":{"범": "0N"},+ "汏":{"대": "1N"},+ "汐":{"석": "0N"},+ "汒":{"망": "1N"},+ "汓":{"수": "N"},+ "汔":{"흘": "1N"},+ "汕":{"산": "0N"},+ "汗":{"한": "0E"},+ "汙":{"오": "1N"},+ "汚":{"오": "0E"},+ "汛":{"신": "1N"},+ "汜":{"사": "1N"},+ "汝":{"여": "0E"},+ "汞":{"홍": "0N"},+ "江":{"강": "0E"},+ "池":{"지": "0E"},+ "汦":{"지": "N"},+ "汨":{"골": "0N"},+ "汩":{"율": "N"},+ "汪":{"왕": "0N"},+ "汭":{"예": "0N"},+ "汰":{"태": "0N"},+ "汲":{"급": "0N"},+ "汴":{"판": "1"},+ "汶":{"문": "0N"},+ "決":{"결": "0E"},+ "汽":{"기": "0N"},+ "汾":{"분": "0N"},+ "沁":{"심": "0N"},+ "沂":{"기": "0N"},+ "沃":{"옥": "0N"},+ "沄":{"운": "1N"},+ "沅":{"원": "0N"},+ "沆":{"항": "0N"},+ "沇":{"연": "0N", "윤": "N"},+ "沈":{"심": "0N", "침": "0E"},+ "沉":{"침": "1"},+ "沌":{"돈": "0N"},+ "沍":{"호": "1N"},+ "沐":{"목": "0N"},+ "沒":{"몰": "0E"},+ "沓":{"답": "0N"},+ "沔":{"면": "0N"},+ "沕":{"물": "0N"},+ "沖":{"충": "0N"},+ "沘":{"비": "1N"},+ "沙":{"사": "0E"},+ "沚":{"지": "0N"},+ "沛":{"패": "0N"},+ "沫":{"말": "0N"},+ "沬":{"매": "1N"},+ "沮":{"저": "0N"},+ "沰":{"탁": "1N"},+ "沱":{"타": "1N"},+ "河":{"하": "0E"},+ "沶":{"시": "N"},+ "沸":{"비": "0N"},+ "油":{"유": "0E"},+ "治":{"치": "0E"},+ "沼":{"소": "0N"},+ "沽":{"고": "0N"},+ "沾":{"첨": "0N"},+ "沿":{"연": "0E"},+ "況":{"황": "0E"},+ "泂":{"형": "0N"},+ "泄":{"설": "0N"},+ "泅":{"수": "1N"},+ "泆":{"일": "1N"},+ "泉":{"천": "0E"},+ "泊":{"박": "0E"},+ "泌":{"비": "0N", "필": "0N"},+ "泐":{"륵": "1N"},+ "泑":{"유": "1N"},+ "泓":{"홍": "0N"},+ "泔":{"감": "1N"},+ "法":{"법": "0E"},+ "泗":{"사": "0N"},+ "泙":{"평": "1N"},+ "泚":{"자": "1N"},+ "泛":{"범": "0N"},+ "泜":{"지": "1N"},+ "泝":{"소": "1N"},+ "泠":{"령": "1N"},+ "泡":{"포": "0N"},+ "波":{"파": "0E"},+ "泣":{"읍": "0E"},+ "泥":{"니": "0E", "이": "0"},+ "注":{"주": "0E"},+ "泫":{"현": "0N"},+ "泮":{"반": "0N"},+ "泯":{"민": "0N"},+ "泰":{"태": "0E"},+ "泱":{"앙": "1N"},+ "泳":{"영": "0E"},+ "泿":{"은": "N"},+ "洄":{"회": "1N"},+ "洇":{"인": "1N"},+ "洊":{"천": "1N"},+ "洋":{"양": "0E"},+ "洌":{"렬": "0N"},+ "洑":{"보": "0N"},+ "洒":{"선": "N", "세": "1N"},+ "洔":{"지": "N"},+ "洗":{"선": "N", "세": "0E"},+ "洙":{"수": "0N"},+ "洛":{"낙": "0", "락": "0N"},+ "洞":{"동": "0E", "통": "0N"},+ "洟":{"이": "1N"},+ "洣":{"미": "N"},+ "津":{"진": "0N"},+ "洧":{"유": "0N"},+ "洨":{"효": "N"},+ "洩":{"설": "0N"},+ "洪":{"홍": "0E"},+ "洫":{"혁": "1N"},+ "洬":{"속": "1N"},+ "洮":{"도": "1N"},+ "洲":{"주": "0E"},+ "洵":{"순": "0N"},+ "洶":{"흉": "0N"},+ "洸":{"광": "0N"},+ "洹":{"원": "0N", "환": "N"},+ "洺":{"명": "1N"},+ "活":{"활": "0E"},+ "洼":{"와": "1N"},+ "洽":{"흡": "0N"},+ "派":{"파": "0E"},+ "流":{"류": "0E", "유": "0"},+ "浙":{"절": "0N"},+ "浚":{"준": "0N"},+ "浜":{"빈": "0N"},+ "浡":{"발": "1N"},+ "浣":{"완": "0N"},+ "浤":{"굉": "1N"},+ "浥":{"읍": "1N"},+ "浦":{"포": "0E"},+ "浧":{"영": "1N"},+ "浩":{"호": "0E"},+ "浪":{"낭": "0", "랑": "0E"},+ "浬":{"리": "0N"},+ "浮":{"부": "0E"},+ "浯":{"오": "N"},+ "浲":{"봉": "N"},+ "浴":{"욕": "0E"},+ "海":{"해": "0EN"},+ "浸":{"침": "0E"},+ "浹":{"협": "0N"},+ "浿":{"패": "0N"},+ "涂":{"도": "1N"},+ "涅":{"열": "0"},+ "涇":{"경": "0N"},+ "消":{"소": "0E"},+ "涉":{"섭": "0E"},+ "涌":{"용": "0N"},+ "涍":{"효": "0N"},+ "涎":{"연": "0N"},+ "涏":{"정": "N"},+ "涑":{"속": "0N"},+ "涓":{"연": "0N"},+ "涔":{"잠": "1N"},+ "涕":{"체": "0N"},+ "涖":{"리": "1N"},+ "涗":{"세": "N"},+ "涪":{"부": "1N"},+ "涫":{"관": "1N"},+ "涬":{"행": "N"},+ "涯":{"애": "0E"},+ "液":{"액": "0N"},+ "涴":{"완": "1N"},+ "涵":{"함": "0N"},+ "涷":{"동": "1N"},+ "涸":{"후": "1"},+ "涼":{"량": "1E"},+ "涿":{"탁": "1N"},+ "淀":{"정": "0N"},+ "淃":{"권": "0N"},+ "淄":{"치": "0N"},+ "淅":{"석": "0N"},+ "淆":{"효": "0N"},+ "淇":{"기": "0N"},+ "淈":{"굴": "1N"},+ "淋":{"림": "0N", "임": "0"},+ "淌":{"창": "N"},+ "淏":{"호": "0N"},+ "淐":{"창": "N"},+ "淑":{"숙": "0E"},+ "淒":{"처": "1N"},+ "淖":{"뇨": "1N"},+ "淘":{"도": "0N"},+ "淙":{"종": "0N"},+ "淚":{"누": "0", "루": "0E"},+ "淝":{"비": "1N"},+ "淞":{"송": "0N"},+ "淠":{"비": "1N"},+ "淡":{"담": "0E"},+ "淢":{"역": "1N"},+ "淣":{"예": "N"},+ "淤":{"어": "1N"},+ "淥":{"록": "1N"},+ "淦":{"감": "1N"},+ "淨":{"정": "0E"},+ "淪":{"륜": "0N", "윤": "0"},+ "淫":{"음": "0E"},+ "淬":{"쉬": "1N"},+ "淮":{"회": "0N"},+ "深":{"심": "0E"},+ "淳":{"순": "0N"},+ "淵":{"연": "0N"},+ "淶":{"래": "1N"},+ "混":{"혼": "0E"},+ "淸":{"청": "0E"},+ "淹":{"엄": "0N"},+ "淺":{"천": "0E"},+ "添":{"첨": "0E"},+ "淼":{"묘": "1N"},+ "清":{"청": "N"},+ "済":{"제": "N"},+ "渊":{"연": "N"},+ "渗":{"삼": "0"},+ "渙":{"환": "0N"},+ "渚":{"저": "0N"},+ "減":{"감": "0E"},+ "渝":{"투": "1N"},+ "渟":{"정": "0N"},+ "渠":{"거": "0N"},+ "渡":{"도": "0E"},+ "渢":{"범": "N"},+ "渣":{"사": "0N"},+ "渤":{"발": "0N"},+ "渥":{"악": "0N"},+ "渦":{"와": "0N"},+ "渨":{"외": "1N"},+ "渫":{"설": "0N"},+ "測":{"측": "0E"},+ "渭":{"위": "0N"},+ "港":{"항": "0E"},+ "渲":{"선": "0N"},+ "渴":{"갈": "0E"},+ "渶":{"영": "0N"},+ "渷":{"연": "1N"},+ "游":{"유": "0N"},+ "渺":{"묘": "0N"},+ "渼":{"미": "0N"},+ "渽":{"재": "0N"},+ "渾":{"혼": "0N"},+ "湀":{"규": "N"},+ "湃":{"배": "0N"},+ "湄":{"미": "0N"},+ "湅":{"련": "1N"},+ "湊":{"주": "0N"},+ "湍":{"단": "0N"},+ "湎":{"면": "1N"},+ "湑":{"서": "1N"},+ "湓":{"분": "1N"},+ "湔":{"전": "1N"},+ "湕":{"건": "N"},+ "湖":{"호": "0E"},+ "湘":{"상": "0N"},+ "湛":{"담": "0N"},+ "湜":{"식": "0N"},+ "湞":{"정": "0N"},+ "湟":{"황": "0N"},+ "湣":{"민": "1", "혼": "N"},+ "湧":{"용": "0N"},+ "湫":{"추": "0N"},+ "湮":{"인": "0N"},+ "湯":{"탕": "0E"},+ "湲":{"원": "0N"},+ "湳":{"남": "0N"},+ "湵":{"유": "N"},+ "湺":{"보": "0N"},+ "溏":{"당": "1N"},+ "源":{"원": "0E"},+ "溕":{"몽": "1N"},+ "準":{"준": "0E"},+ "溘":{"합": "1N"},+ "溜":{"류": "0N", "유": "0"},+ "溝":{"구": "0N"},+ "溟":{"명": "0N"},+ "溢":{"일": "0N"},+ "溥":{"부": "0N"},+ "溧":{"률": "1N"},+ "溨":{"재": "N"},+ "溪":{"계": "0E"},+ "溫":{"온": "0E"},+ "溯":{"소": "0N"},+ "溱":{"진": "0N"},+ "溲":{"수": "1N"},+ "溵":{"은": "1N"},+ "溶":{"용": "0N"},+ "溷":{"혼": "1N"},+ "溺":{"닉": "0N", "익": "0"},+ "溽":{"욕": "1N"},+ "滂":{"방": "0N"},+ "滃":{"옹": "1N"},+ "滄":{"창": "0N"},+ "滅":{"멸": "0E"},+ "滈":{"호": "1N"},+ "滉":{"황": "0N"},+ "滋":{"자": "0N"},+ "滌":{"척": "0N"},+ "滎":{"형": "0N"},+ "滑":{"골": "0N", "활": "0N"},+ "滓":{"재": "0N"},+ "滔":{"도": "0N"},+ "滕":{"등": "1N"},+ "滙":{"회": "1"},+ "滬":{"호": "1N"},+ "滭":{"필": "1N"},+ "滯":{"체": "0E"},+ "滲":{"삼": "N"},+ "滴":{"적": "0E"},+ "滵":{"밀": "1N"},+ "滷":{"로": "1N"},+ "滸":{"호": "0N"},+ "滼":{"범": "N"},+ "滾":{"곤": "0N"},+ "滿":{"만": "0E"},+ "漁":{"어": "0E"},+ "漂":{"표": "0E"},+ "漄":{"애": "1N"},+ "漆":{"칠": "0E"},+ "漉":{"록": "1N"},+ "漌":{"근": "1N"},+ "漏":{"누": "0", "루": "0E"},+ "漑":{"개": "0N"},+ "漓":{"리": "1N"},+ "演":{"연": "0E"},+ "漕":{"조": "0N"},+ "漙":{"단": "1N"},+ "漚":{"구": "1N"},+ "漠":{"막": "0E"},+ "漢":{"한": "0E"},+ "漣":{"련": "0N", "연": "0"},+ "漤":{"람": "N"},+ "漦":{"시": "N"},+ "漧":{"건": "N"},+ "漨":{"봉": "N"},+ "漪":{"의": "1N"},+ "漫":{"만": "0E"},+ "漬":{"지": "0N"},+ "漭":{"망": "1N"},+ "漰":{"붕": "1N"},+ "漱":{"수": "0N"},+ "漲":{"창": "0N"},+ "漳":{"장": "1N"},+ "漸":{"점": "0E"},+ "漼":{"최": "1N"},+ "漾":{"양": "1N"},+ "漿":{"장": "0N"},+ "潁":{"영": "0N"},+ "潏":{"율": "1N"},+ "潑":{"발": "0N"},+ "潒":{"상": "N"},+ "潔":{"결": "0E"},+ "潗":{"집": "0N"},+ "潘":{"반": "0N"},+ "潙":{"규": "1N"},+ "潚":{"숙": "0N"},+ "潛":{"잠": "0E"},+ "潜":{"잠": "1N"},+ "潝":{"흡": "1N"},+ "潞":{"로": "0N"},+ "潟":{"석": "0N"},+ "潡":{"돈": "1N"},+ "潢":{"황": "0N"},+ "潣":{"민": "N"},+ "潤":{"윤": "0E"},+ "潦":{"로": "N", "료": "1N"},+ "潭":{"담": "0N"},+ "潮":{"조": "0E"},+ "潯":{"심": "1N"},+ "潰":{"궤": "0N"},+ "潱":{"열": "N"},+ "潴":{"저": "1N"},+ "潸":{"산": "1N"},+ "潺":{"잔": "0N"},+ "潼":{"동": "0N"},+ "潽":{"보": "0N"},+ "潾":{"린": "0N"},+ "澁":{"삽": "0N"},+ "澂":{"징": "1N"},+ "澄":{"징": "0N"},+ "澆":{"요": "1N"},+ "澇":{"로": "N"},+ "澈":{"철": "0N"},+ "澉":{"감": "1N"},+ "澋":{"횡": "1N"},+ "澌":{"시": "1N"},+ "澍":{"주": "0N"},+ "澎":{"팽": "0N"},+ "澐":{"운": "0N"},+ "澒":{"홍": "1N"},+ "澔":{"호": "0N"},+ "澕":{"화": "N"},+ "澖":{"한": "N"},+ "澗":{"간": "0N"},+ "澘":{"산": "1N"},+ "澟":{"름": "1N"},+ "澡":{"조": "1N"},+ "澣":{"한": "0N"},+ "澤":{"택": "0E"},+ "澥":{"해": "N"},+ "澧":{"례": "0N"},+ "澨":{"서": "1N"},+ "澪":{"령": "N"},+ "澮":{"회": "0N"},+ "澯":{"찬": "0N"},+ "澱":{"전": "0N"},+ "澳":{"오": "0N"},+ "澶":{"전": "1N"},+ "澹":{"담": "0N"},+ "澾":{"달": "0N"},+ "激":{"격": "0E"},+ "濁":{"탁": "0E"},+ "濂":{"렴": "0N"},+ "濃":{"농": "0N"},+ "濆":{"분": "1N"},+ "濇":{"색": "1N"},+ "濉":{"수": "1N"},+ "濊":{"예": "0N"},+ "濔":{"니": "N", "미": "N"},+ "濕":{"습": "0E"},+ "濘":{"녕": "1N"},+ "濚":{"영": "0N"},+ "濛":{"몽": "1N"},+ "濞":{"비": "1N"},+ "濟":{"제": "0E"},+ "濠":{"호": "0N"},+ "濡":{"유": "0N"},+ "濤":{"도": "0N"},+ "濥":{"인": "N"},+ "濦":{"은": "N"},+ "濩":{"호": "0N"},+ "濫":{"남": "0", "람": "0E"},+ "濬":{"준": "0N"},+ "濮":{"복": "1N"},+ "濯":{"탁": "0E"},+ "濱":{"빈": "0N"},+ "濳":{"잠": "1"},+ "濴":{"영": "1N"},+ "濶":{"활": "N"},+ "濺":{"천": "1N"},+ "濾":{"려": "0N", "여": "0"},+ "瀁":{"양": "0N"},+ "瀅":{"형": "0N"},+ "瀆":{"독": "0N"},+ "瀇":{"왕": "1N"},+ "瀉":{"사": "0N"},+ "瀋":{"심": "0N"},+ "瀏":{"류": "0N"},+ "瀑":{"폭": "0N"},+ "瀒":{"색": "1N"},+ "瀓":{"징": "1N"},+ "瀕":{"빈": "0N"},+ "瀘":{"로": "0N"},+ "瀚":{"한": "0N"},+ "瀛":{"영": "0N"},+ "瀜":{"융": "0N"},+ "瀝":{"력": "0N"},+ "瀞":{"정": "0N"},+ "瀟":{"소": "0N"},+ "瀣":{"해": "0N"},+ "瀦":{"저": "1N"},+ "瀧":{"롱": "0N"},+ "瀨":{"뢰": "0N"},+ "瀯":{"영": "0N"},+ "瀰":{"미": "1N"},+ "瀲":{"렴": "1N"},+ "瀷":{"익": "0N"},+ "瀸":{"첨": "1N"},+ "瀼":{"양": "1N"},+ "瀾":{"란": "0N"},+ "灄":{"섭": "1N"},+ "灆":{"람": "N"},+ "灌":{"관": "0N"},+ "灎":{"염": "1"},+ "灐":{"형": "0N"},+ "灑":{"쇄": "0N"},+ "灓":{"란": "1N"},+ "灘":{"탄": "0N"},+ "灝":{"호": "0N"},+ "灞":{"파": "1N"},+ "灣":{"만": "0N"},+ "灦":{"현": "N"},+ "灩":{"염": "1N"},+ "火":{"화": "0E"},+ "灯":{"정": "1N"},+ "灰":{"회": "0N"},+ "灸":{"구": "0N"},+ "灼":{"작": "0N"},+ "災":{"재": "0E"},+ "灾":{"재": "1N"},+ "炁":{"기": "1N"},+ "炅":{"경": "0N"},+ "炆":{"문": "1N"},+ "炊":{"취": "0N"},+ "炎":{"담": "N", "염": "0E"},+ "炒":{"초": "0N"},+ "炕":{"항": "1N"},+ "炘":{"흔": "0N"},+ "炙":{"자": "0N", "적": "0N"},+ "炚":{"광": "0N"},+ "炛":{"광": "N"},+ "炡":{"정": "0N"},+ "炤":{"소": "0N"},+ "炦":{"발": "N", "별": "N"},+ "炫":{"현": "0N"},+ "炬":{"거": "0N"},+ "炭":{"탄": "0E"},+ "炮":{"포": "1N"},+ "炯":{"형": "0N"},+ "炰":{"포": "1N"},+ "炳":{"병": "0N"},+ "炷":{"주": "0N"},+ "炸":{"작": "0N"},+ "点":{"점": "0N"},+ "烈":{"렬": "0E", "열": "0"},+ "烊":{"양": "1N"},+ "烋":{"효": "N", "휴": "0N"},+ "烏":{"오": "0E"},+ "烓":{"계": "1N"},+ "烔":{"동": "N"},+ "烘":{"홍": "0N"},+ "烙":{"낙": "0", "락": "0N"},+ "烜":{"훤": "1N"},+ "烝":{"증": "0N"},+ "烟":{"연": "0N"},+ "烯":{"희": "N"},+ "烱":{"경": "0N"},+ "烹":{"팽": "0N"},+ "烺":{"랑": "N"},+ "烽":{"봉": "0N"},+ "焃":{"혁": "N"},+ "焄":{"훈": "0N"},+ "焆":{"결": "N"},+ "焉":{"언": "0E"},+ "焌":{"준": "0N"},+ "焙":{"배": "0N"},+ "焚":{"분": "0N"},+ "焜":{"혼": "1N"},+ "焞":{"돈": "0N", "순": "N"},+ "焠":{"쉬": "1N"},+ "無":{"무": "0E"},+ "焦":{"초": "0N"},+ "焭":{"경": "1N"},+ "焮":{"흔": "1"},+ "焯":{"작": "1N"},+ "焰":{"염": "0N"},+ "焱":{"혁": "1N"},+ "然":{"연": "0E"},+ "煃":{"규": "N"},+ "煆":{"하": "1N"},+ "煇":{"훈": "N", "휘": "0N"},+ "煉":{"련": "0N", "연": "0"},+ "煊":{"훤": "0N"},+ "煌":{"황": "0N"},+ "煎":{"전": "0N"},+ "煐":{"영": "0N"},+ "煒":{"위": "1", "휘": "N"},+ "煓":{"단": "N"},+ "煕":{"희": "N"},+ "煖":{"난": "0N"},+ "煗":{"난": "1"},+ "煙":{"연": "0E"},+ "煜":{"욱": "0N"},+ "煝":{"미": "N"},+ "煞":{"살": "0N"},+ "煢":{"경": "1N"},+ "煤":{"매": "0N"},+ "煥":{"환": "0N"},+ "煦":{"후": "0N"},+ "照":{"조": "0E"},+ "煨":{"외": "1N"},+ "煩":{"번": "0E"},+ "煬":{"양": "0N"},+ "煮":{"자": "0N"},+ "煽":{"선": "0N"},+ "熀":{"엽": "1N", "황": "N"},+ "熄":{"식": "0N"},+ "熅":{"온": "1N"},+ "熇":{"혹": "N", "효": "1N"},+ "熈":{"희": "N"},+ "熉":{"운": "0N"},+ "熊":{"웅": "0N"},+ "熏":{"훈": "0N"},+ "熒":{"형": "0N"},+ "熔":{"용": "0N"},+ "熙":{"희": "0N"},+ "熛":{"표": "1N"},+ "熟":{"숙": "0E"},+ "熠":{"습": "1"},+ "熡":{"루": "N"},+ "熢":{"봉": "0N"},+ "熤":{"익": "1N"},+ "熨":{"위": "1N"},+ "熩":{"호": "N"},+ "熬":{"오": "0N"},+ "熯":{"선": "1"},+ "熱":{"열": "0E"},+ "熲":{"경": "1N"},+ "熹":{"희": "0N"},+ "熺":{"희": "0N"},+ "熾":{"치": "0N"},+ "燁":{"엽": "0N"},+ "燃":{"연": "0E"},+ "燈":{"등": "0E"},+ "燉":{"돈": "0N"},+ "燋":{"초": "1N"},+ "燎":{"료": "0N", "요": "0"},+ "燏":{"율": "N"},+ "燐":{"린": "0N", "인": "0"},+ "燒":{"소": "0E"},+ "燔":{"번": "0N"},+ "燕":{"연": "0E"},+ "燖":{"심": "1N"},+ "燙":{"탕": "1N"},+ "燛":{"경": "N"},+ "營":{"영": "0E"},+ "燠":{"오": "N", "우": "N", "욱": "1N"},+ "燥":{"조": "0E"},+ "燦":{"찬": "0N"},+ "燧":{"수": "0N"},+ "燬":{"훼": "1N"},+ "燭":{"촉": "0E"},+ "燮":{"섭": "0N"},+ "燹":{"희": "1N"},+ "燻":{"훈": "0N"},+ "燼":{"신": "0N"},+ "燽":{"주": "N"},+ "燾":{"도": "0N"},+ "燿":{"요": "0N"},+ "爀":{"혁": "0N"},+ "爁":{"람": "N"},+ "爆":{"폭": "0E"},+ "爇":{"설": "1N"},+ "爋":{"훈": "1"},+ "爌":{"광": "1N"},+ "爍":{"삭": "1N"},+ "爐":{"노": "0", "로": "0E"},+ "爔":{"희": "1N"},+ "爗":{"엽": "1N"},+ "爚":{"약": "1N"},+ "爛":{"난": "0", "란": "0N"},+ "爟":{"관": "1N"},+ "爥":{"촉": "1N"},+ "爨":{"찬": "1N"},+ "爪":{"조": "0N"},+ "爬":{"파": "0N"},+ "爭":{"쟁": "0E"},+ "爰":{"원": "0N"},+ "爲":{"위": "0E"},+ "爵":{"작": "0E"},+ "父":{"부": "0E"},+ "爸":{"파": "1N"},+ "爹":{"다": "1N"},+ "爺":{"야": "0N"},+ "爻":{"효": "0N"},+ "爽":{"상": "0N"},+ "爾":{"이": "0N"},+ "牀":{"상": "0N"},+ "牂":{"장": "1N"},+ "牆":{"장": "0N"},+ "片":{"편": "0E"},+ "版":{"판": "0E"},+ "牋":{"전": "1N"},+ "牌":{"패": "0N"},+ "牒":{"첩": "0N"},+ "牓":{"방": "1N"},+ "牔":{"박": "1N"},+ "牖":{"유": "1N"},+ "牘":{"독": "0N"},+ "牙":{"아": "0E"},+ "牚":{"탱": "1N"},+ "牛":{"우": "0E"},+ "牝":{"빈": "0N"},+ "牟":{"모": "0N"},+ "牡":{"모": "0N"},+ "牢":{"뇌": "0", "뢰": "0N"},+ "牣":{"인": "N"},+ "牧":{"목": "0E"},+ "物":{"물": "0E"},+ "牯":{"고": "1N"},+ "牲":{"생": "0N"},+ "牴":{"저": "1N"},+ "牸":{"자": "1N"},+ "特":{"특": "0E"},+ "牽":{"견": "0E"},+ "犀":{"서": "0N"},+ "犁":{"리": "0N"},+ "犂":{"리": "N"},+ "犇":{"분": "1N"},+ "犍":{"건": "1N"},+ "犒":{"호": "1N"},+ "犖":{"락": "1N"},+ "犢":{"독": "0N"},+ "犧":{"희": "0N"},+ "犬":{"견": "0E"},+ "犯":{"범": "0E"},+ "犳":{"작": "1N"},+ "犴":{"안": "1N"},+ "犵":{"힐": "1N"},+ "狀":{"상": "0E", "장": "0N"},+ "狂":{"광": "0E"},+ "狄":{"적": "0N"},+ "狉":{"비": "1N"},+ "狎":{"압": "0N"},+ "狐":{"호": "0N"},+ "狒":{"비": "1N"},+ "狗":{"구": "0E"},+ "狙":{"저": "0N"},+ "狡":{"교": "0N"},+ "狢":{"학": "1N"},+ "狥":{"순": "1"},+ "狨":{"융": "1N"},+ "狩":{"수": "0N"},+ "狴":{"폐": "1N"},+ "狷":{"견": "1N"},+ "狸":{"리": "0N"},+ "狹":{"협": "0N"},+ "狺":{"은": "1N"},+ "狻":{"산": "1N"},+ "狼":{"낭": "0", "랑": "0N"},+ "狽":{"패": "0N"},+ "猉":{"기": "1N"},+ "猊":{"예": "0N"},+ "猓":{"과": "1N"},+ "猖":{"창": "0N"},+ "猗":{"아": "N", "의": "1N"},+ "猘":{"제": "1N"},+ "猙":{"쟁": "1N"},+ "猛":{"맹": "0E"},+ "猜":{"시": "0N"},+ "猝":{"졸": "0N"},+ "猢":{"호": "1N"},+ "猥":{"외": "0N"},+ "猧":{"와": "1N"},+ "猨":{"원": "1N"},+ "猩":{"성": "0N"},+ "猪":{"저": "0N"},+ "猫":{"묘": "0N"},+ "猱":{"노": "1N"},+ "猴":{"후": "1N"},+ "猶":{"유": "0E"},+ "猷":{"유": "0N"},+ "猾":{"활": "0N"},+ "猿":{"원": "0N"},+ "獃":{"애": "1N"},+ "獄":{"옥": "0E"},+ "獅":{"사": "0N"},+ "獎":{"장": "N"},+ "獐":{"장": "0N"},+ "獒":{"오": "0N"},+ "獗":{"궐": "0N"},+ "獘":{"폐": "1N"},+ "獜":{"린": "1N"},+ "獠":{"료": "1N"},+ "獨":{"독": "0E"},+ "獩":{"예": "1N"},+ "獪":{"회": "0N"},+ "獫":{"험": "1N"},+ "獬":{"해": "1N"},+ "獯":{"훈": "1N"},+ "獰":{"녕": "N", "영": "0"},+ "獲":{"획": "0E"},+ "獵":{"렵": "0E", "엽": "0"},+ "獷":{"광": "1N"},+ "獸":{"수": "0E"},+ "獺":{"달": "0N"},+ "獻":{"헌": "0E"},+ "獼":{"미": "1N"},+ "玁":{"험": "1N"},+ "玄":{"현": "0E"},+ "玆":{"자": "0N"},+ "率":{"률": "0E", "솔": "0N", "율": "0"},+ "玈":{"로": "1N"},+ "玉":{"옥": "0E"},+ "王":{"왕": "0E"},+ "玎":{"정": "0N"},+ "玒":{"강": "N"},+ "玔":{"천": "0N"},+ "玕":{"간": "1N"},+ "玖":{"구": "0N"},+ "玗":{"우": "0N"},+ "玘":{"기": "0N"},+ "玞":{"부": "1N"},+ "玟":{"민": "0N"},+ "玠":{"개": "1N"},+ "玦":{"결": "1N"},+ "玧":{"윤": "0N"},+ "玩":{"완": "0N"},+ "玪":{"감": "N", "림": "N"},+ "玫":{"매": "1N"},+ "玭":{"빈": "0N"},+ "玲":{"령": "0N", "영": "0"},+ "玳":{"대": "0N"},+ "玴":{"예": "N"},+ "玷":{"점": "1N"},+ "玹":{"현": "0N"},+ "玻":{"파": "1N"},+ "玼":{"체": "N"},+ "玽":{"구": "N"},+ "玿":{"소": "N"},+ "珀":{"박": "0N", "백": "N"},+ "珂":{"가": "0N"},+ "珆":{"이": "1N", "태": "N"},+ "珈":{"가": "1N"},+ "珉":{"민": "0N"},+ "珊":{"산": "0N"},+ "珌":{"필": "0N"},+ "珍":{"진": "0E"},+ "珏":{"각": "0N"},+ "珒":{"진": "1N"},+ "珖":{"광": "0N"},+ "珗":{"선": "N"},+ "珘":{"주": "N"},+ "珙":{"공": "0N"},+ "珝":{"후": "0N"},+ "珞":{"낙": "0", "락": "0N"},+ "珠":{"주": "0E"},+ "珢":{"은": "1N"},+ "珣":{"순": "0N"},+ "珤":{"보": "0N"},+ "珥":{"이": "0N"},+ "珦":{"향": "0N"},+ "珩":{"형": "0N"},+ "珪":{"규": "0N"},+ "珫":{"충": "1N"},+ "班":{"반": "0E"},+ "珮":{"패": "1N"},+ "珵":{"정": "1N"},+ "珷":{"무": "0N"},+ "珸":{"오": "N"},+ "珹":{"성": "0N"},+ "珽":{"정": "0N"},+ "現":{"현": "0E"},+ "琁":{"선": "0N"},+ "球":{"구": "0E"},+ "琄":{"현": "1N"},+ "琅":{"랑": "0N"},+ "理":{"리": "0E", "이": "0"},+ "琇":{"수": "0N"},+ "琉":{"류": "0N", "유": "0"},+ "琓":{"완": "0N"},+ "琗":{"채": "N"},+ "琘":{"민": "N"},+ "琛":{"침": "0N"},+ "琝":{"민": "N"},+ "琟":{"유": "N"},+ "琠":{"전": "0N"},+ "琡":{"숙": "0N"},+ "琢":{"탁": "0N"},+ "琤":{"쟁": "1N"},+ "琥":{"호": "0N"},+ "琦":{"기": "0N"},+ "琨":{"곤": "0N"},+ "琪":{"기": "0N"},+ "琫":{"봉": "0N"},+ "琬":{"완": "0N"},+ "琮":{"종": "0N"},+ "琯":{"관": "0N"},+ "琰":{"염": "0N"},+ "琱":{"조": "1N"},+ "琲":{"배": "1N"},+ "琳":{"림": "0N"},+ "琴":{"금": "0E"},+ "琵":{"비": "0N"},+ "琶":{"파": "0N"},+ "琸":{"탁": "0N"},+ "琺":{"법": "0N"},+ "琿":{"혼": "0N"},+ "瑀":{"우": "0N"},+ "瑁":{"모": "0N"},+ "瑂":{"미": "N"},+ "瑃":{"춘": "0N"},+ "瑄":{"선": "0N"},+ "瑅":{"제": "1N"},+ "瑆":{"성": "1N"},+ "瑈":{"유": "N"},+ "瑉":{"민": "N"},+ "瑋":{"위": "0N"},+ "瑌":{"연": "N"},+ "瑎":{"해": "1N"},+ "瑕":{"하": "0N"},+ "瑗":{"원": "0N"},+ "瑙":{"노": "0N"},+ "瑚":{"호": "0N"},+ "瑛":{"영": "0N"},+ "瑜":{"유": "0N"},+ "瑝":{"황": "1N"},+ "瑞":{"서": "0N"},+ "瑟":{"슬": "0N"},+ "瑠":{"류": "0N"},+ "瑢":{"용": "0N"},+ "瑣":{"쇄": "1N"},+ "瑤":{"요": "0N"},+ "瑥":{"온": "0N"},+ "瑨":{"진": "0N"},+ "瑩":{"영": "0N", "형": "0N"},+ "瑪":{"마": "0N"},+ "瑭":{"당": "1N"},+ "瑮":{"률": "N"},+ "瑯":{"랑": "0N"},+ "瑰":{"괴": "1N"},+ "瑱":{"전": "1", "진": "N"},+ "瑲":{"창": "1N"},+ "瑳":{"차": "1N"},+ "瑽":{"종": "1N"},+ "瑾":{"근": "0N"},+ "璀":{"최": "1N"},+ "璂":{"기": "0N"},+ "璃":{"리": "0N"},+ "璄":{"경": "N"},+ "璅":{"소": "N"},+ "璆":{"구": "1N"},+ "璇":{"선": "0N"},+ "璉":{"련": "0N", "연": "0"},+ "璊":{"문": "1N"},+ "璋":{"장": "0N"},+ "璌":{"인": "N"},+ "璐":{"로": "N"},+ "璘":{"린": "0N", "인": "0"},+ "璜":{"황": "0N"},+ "璝":{"괴": "1N"},+ "璞":{"박": "0N"},+ "璟":{"경": "0N"},+ "璡":{"진": "0N"},+ "璣":{"기": "0N"},+ "璥":{"경": "0N"},+ "璧":{"벽": "0N"},+ "璨":{"찬": "0N"},+ "璪":{"조": "0N"},+ "璫":{"당": "1N"},+ "環":{"환": "0E"},+ "璱":{"슬": "N"},+ "璲":{"수": "0N"},+ "璵":{"여": "0N"},+ "璶":{"신": "N"},+ "璸":{"빈": "N"},+ "璹":{"숙": "0N"},+ "璼":{"람": "N"},+ "璽":{"새": "0N"},+ "璿":{"선": "0N"},+ "瓀":{"연": "N"},+ "瓆":{"질": "0N"},+ "瓊":{"경": "0N"},+ "瓍":{"수": "N"},+ "瓏":{"롱": "0N"},+ "瓐":{"로": "N"},+ "瓓":{"란": "N"},+ "瓔":{"영": "0N"},+ "瓘":{"관": "0N"},+ "瓚":{"찬": "0N"},+ "瓛":{"환": "1N"},+ "瓜":{"과": "0N"},+ "瓠":{"호": "0N"},+ "瓢":{"표": "0N"},+ "瓣":{"판": "0N"},+ "瓦":{"와": "0E"},+ "瓩":{"천": "1"},+ "瓮":{"옹": "0N"},+ "瓲":{"톤": "1"},+ "瓳":{"호": "N"},+ "瓷":{"자": "0N"},+ "甁":{"병": "0N"},+ "甃":{"추": "1N"},+ "甄":{"견": "0N"},+ "甌":{"구": "1N"},+ "甍":{"맹": "1N"},+ "甎":{"전": "1N"},+ "甑":{"증": "0N"},+ "甓":{"벽": "1N"},+ "甕":{"옹": "0N"},+ "甘":{"감": "0E"},+ "甚":{"심": "0E"},+ "甛":{"첨": "0N"},+ "甜":{"첨": "N"},+ "甞":{"상": "1N"},+ "生":{"생": "0E"},+ "產":{"산": "N"},+ "産":{"산": "0E"},+ "甤":{"유": "N"},+ "甥":{"생": "0N"},+ "甦":{"소": "0N"},+ "用":{"용": "0E"},+ "甫":{"보": "0N"},+ "甬":{"용": "0N"},+ "田":{"전": "0E"},+ "由":{"유": "0E"},+ "甲":{"갑": "0E"},+ "申":{"신": "0E"},+ "男":{"남": "0E"},+ "甸":{"전": "0N"},+ "町":{"정": "0N"},+ "画":{"획": "N"},+ "甿":{"맹": "1N"},+ "畃":{"순": "N"},+ "畇":{"균": "0N"},+ "畊":{"경": "1N"},+ "畋":{"전": "1N"},+ "界":{"계": "0E"},+ "畎":{"견": "1N"},+ "畏":{"외": "0E"},+ "畑":{"전": "0N"},+ "畓":{"답": "0E"},+ "畔":{"반": "0N"},+ "留":{"류": "0E", "유": "0"},+ "畚":{"분": "1N"},+ "畛":{"진": "0N"},+ "畜":{"축": "0E"},+ "畝":{"묘": "N", "무": "0N"},+ "畠":{"전": "1"},+ "畢":{"필": "0E"},+ "畤":{"치": "1N"},+ "略":{"략": "0E", "약": "0"},+ "畦":{"휴": "0N"},+ "畧":{"략": "1N"},+ "番":{"번": "0E"},+ "畫":{"화": "1E"},+ "畯":{"준": "0N"},+ "異":{"리": "0", "이": "0E"},+ "畵":{"화": "0N"},+ "當":{"당": "0E"},+ "畸":{"기": "0N"},+ "畺":{"강": "0N"},+ "畿":{"기": "0E"},+ "疆":{"강": "0N"},+ "疇":{"주": "0N"},+ "疈":{"벽": "1N"},+ "疊":{"첩": "0N"},+ "疋":{"필": "0N"},+ "疎":{"소": "0N"},+ "疏":{"소": "0E"},+ "疑":{"의": "0E"},+ "疔":{"정": "1N"},+ "疙":{"흘": "1N"},+ "疚":{"구": "1N"},+ "疝":{"산": "0N"},+ "疣":{"우": "1N"},+ "疥":{"개": "0N"},+ "疩":{"췌": "1"},+ "疫":{"역": "0E"},+ "疱":{"포": "0N"},+ "疲":{"피": "0E"},+ "疳":{"감": "0N"},+ "疴":{"아": "1N"},+ "疵":{"자": "0N"},+ "疸":{"달": "0N"},+ "疹":{"진": "0N"},+ "疼":{"동": "0N"},+ "疽":{"저": "0N"},+ "疾":{"질": "0E"},+ "痀":{"구": "1N"},+ "痂":{"가": "0N"},+ "痃":{"현": "1N"},+ "病":{"병": "0E"},+ "症":{"증": "0E"},+ "痊":{"전": "1N"},+ "痍":{"이": "0N"},+ "痎":{"해": "1N"},+ "痒":{"양": "0N"},+ "痓":{"치": "1N"},+ "痔":{"치": "0N"},+ "痕":{"흔": "0N"},+ "痘":{"두": "0N"},+ "痙":{"경": "0N"},+ "痛":{"통": "0E"},+ "痞":{"비": "1N"},+ "痢":{"리": "0N", "이": "0"},+ "痣":{"지": "1N"},+ "痤":{"좌": "1N"},+ "痧":{"사": "1N"},+ "痰":{"담": "0N"},+ "痲":{"마": "0N"},+ "痳":{"림": "1N"},+ "痴":{"치": "0N"},+ "痹":{"비": "1N"},+ "痺":{"비": "0N"},+ "痼":{"고": "0N"},+ "痿":{"위": "1N"},+ "瘀":{"어": "0N"},+ "瘁":{"췌": "1N"},+ "瘇":{"종": "1N"},+ "瘈":{"계": "1N"},+ "瘉":{"유": "1N"},+ "瘋":{"풍": "1N"},+ "瘍":{"양": "0N"},+ "瘐":{"유": "1N"},+ "瘕":{"하": "1N"},+ "瘙":{"소": "0N"},+ "瘟":{"온": "0N"},+ "瘠":{"척": "0N"},+ "瘡":{"창": "0N"},+ "瘢":{"반": "0N"},+ "瘤":{"류": "0N"},+ "瘦":{"수": "0N"},+ "瘧":{"학": "1N"},+ "瘯":{"족": "1N"},+ "瘰":{"라": "1N"},+ "瘱":{"예": "N"},+ "瘳":{"추": "1N"},+ "瘴":{"장": "1N"},+ "瘻":{"루": "0N"},+ "療":{"료": "0N", "요": "0"},+ "癃":{"륭": "1N"},+ "癆":{"로": "1N"},+ "癇":{"간": "N"},+ "癈":{"폐": "1N"},+ "癉":{"단": "1N"},+ "癌":{"암": "0N"},+ "癎":{"간": "0N"},+ "癒":{"유": "0N"},+ "癕":{"옹": "1N"},+ "癖":{"벽": "0N"},+ "癘":{"려": "1N"},+ "癜":{"전": "1N"},+ "癡":{"치": "0N"},+ "癢":{"양": "1N"},+ "癤":{"절": "0N"},+ "癥":{"징": "1N"},+ "癧":{"력": "1N"},+ "癨":{"곽": "1N"},+ "癩":{"나": "0", "라": "0N"},+ "癬":{"선": "0N"},+ "癭":{"영": "1N"},+ "癮":{"은": "1N"},+ "癯":{"구": "1N"},+ "癰":{"옹": "0N"},+ "癱":{"탄": "1N"},+ "癲":{"전": "0N"},+ "癸":{"계": "0E"},+ "登":{"등": "0E"},+ "發":{"발": "0E"},+ "白":{"백": "0E"},+ "百":{"백": "0E"},+ "皀":{"급": "1N"},+ "皁":{"조": "1N"},+ "皃":{"모": "1N"},+ "的":{"적": "0E"},+ "皆":{"개": "0E"},+ "皇":{"황": "0E"},+ "皋":{"고": "1N"},+ "皎":{"교": "0N"},+ "皐":{"고": "0N"},+ "皒":{"아": "N"},+ "皓":{"호": "0N"},+ "皖":{"환": "1N"},+ "皗":{"주": "N"},+ "皚":{"애": "1N"},+ "皛":{"효": "1N"},+ "皜":{"호": "1N"},+ "皞":{"호": "1N"},+ "皤":{"파": "1N"},+ "皬":{"학": "1N"},+ "皮":{"피": "0E"},+ "皴":{"준": "1N"},+ "皶":{"사": "1N"},+ "皸":{"군": "1N"},+ "皺":{"추": "0N"},+ "皿":{"명": "0N"},+ "盂":{"우": "0N"},+ "盃":{"배": "0N"},+ "盆":{"분": "0N"},+ "盈":{"영": "0N"},+ "益":{"익": "0E"},+ "盌":{"완": "1N"},+ "盍":{"합": "1N"},+ "盎":{"앙": "1N"},+ "盒":{"합": "0N"},+ "盓":{"우": "N"},+ "盔":{"회": "1N"},+ "盖":{"개": "0N"},+ "盙":{"보": "1N"},+ "盛":{"성": "0EN"},+ "盜":{"도": "0E"},+ "盞":{"잔": "0N"},+ "盟":{"맹": "0E"},+ "盡":{"진": "0E"},+ "監":{"감": "0E"},+ "盤":{"반": "0E"},+ "盥":{"관": "1N"},+ "盧":{"노": "0", "로": "0N"},+ "盪":{"탕": "1N"},+ "盬":{"고": "1N"},+ "目":{"목": "0E"},+ "盱":{"우": "1N"},+ "盲":{"맹": "0E"},+ "直":{"직": "0E"},+ "相":{"상": "0E"},+ "盹":{"순": "1N"},+ "盻":{"혜": "1N"},+ "盼":{"반": "0N"},+ "盾":{"순": "0N"},+ "盿":{"민": "N"},+ "眀":{"명": "N"},+ "省":{"생": "0N", "성": "0E"},+ "眂":{"시": "N"},+ "眄":{"면": "0N"},+ "眇":{"묘": "1N"},+ "眈":{"탐": "0N"},+ "眉":{"미": "0E"},+ "眊":{"모": "1N"},+ "看":{"간": "0E"},+ "県":{"현": "1"},+ "眐":{"정": "N"},+ "眚":{"생": "1N"},+ "眛":{"매": "1N"},+ "眞":{"진": "0E"},+ "真":{"진": "N"},+ "眠":{"면": "0E"},+ "眥":{"자": "1N"},+ "眦":{"자": "1N"},+ "眨":{"잡": "1N"},+ "眩":{"현": "0N"},+ "眴":{"순": "1N"},+ "眷":{"권": "0N"},+ "眸":{"모": "0N"},+ "眹":{"진": "N"},+ "眺":{"조": "0N"},+ "眻":{"양": "1N"},+ "眼":{"안": "0E"},+ "眾":{"중": "1N"},+ "着":{"착": "0E"},+ "睃":{"준": "N"},+ "睆":{"환": "1N"},+ "睇":{"제": "1N"},+ "睍":{"현": "0N"},+ "睒":{"섬": "1N"},+ "睚":{"애": "1N"},+ "睛":{"정": "0N"},+ "睟":{"수": "1N"},+ "睠":{"권": "1N"},+ "睡":{"수": "0E"},+ "睢":{"수": "1N"},+ "督":{"독": "0E"},+ "睥":{"비": "1N"},+ "睦":{"목": "0E"},+ "睨":{"예": "1N"},+ "睫":{"첩": "0N"},+ "睬":{"채": "N"},+ "睷":{"건": "1N"},+ "睹":{"도": "0N"},+ "睽":{"규": "1N"},+ "睾":{"고": "0N"},+ "睿":{"예": "0N"},+ "瞋":{"진": "0N"},+ "瞍":{"수": "1N"},+ "瞎":{"할": "1N"},+ "瞑":{"명": "0N"},+ "瞖":{"예": "1N"},+ "瞙":{"막": "1N"},+ "瞞":{"만": "0N"},+ "瞠":{"당": "1N"},+ "瞢":{"몽": "1N"},+ "瞥":{"별": "0N"},+ "瞪":{"징": "1N"},+ "瞬":{"순": "0E"},+ "瞭":{"료": "0N"},+ "瞮":{"철": "N"},+ "瞰":{"감": "0N"},+ "瞳":{"동": "0N"},+ "瞹":{"애": "1N"},+ "瞻":{"첨": "0N"},+ "瞼":{"검": "0N"},+ "瞽":{"고": "1N"},+ "瞿":{"구": "0N"},+ "矇":{"몽": "1N"},+ "矉":{"빈": "1N"},+ "矍":{"확": "1N"},+ "矗":{"촉": "0N"},+ "矙":{"감": "1N"},+ "矚":{"촉": "1N"},+ "矛":{"모": "0N"},+ "矜":{"긍": "0N"},+ "矞":{"율": "1N"},+ "矡":{"확": "1N"},+ "矢":{"시": "0E"},+ "矣":{"의": "0E"},+ "知":{"지": "0E"},+ "矧":{"신": "1N"},+ "矩":{"구": "0N"},+ "短":{"단": "0E"},+ "矮":{"왜": "0N"},+ "矯":{"교": "0E"},+ "矰":{"증": "1N"},+ "石":{"석": "0E"},+ "矸":{"간": "N", "안": "N"},+ "矺":{"탁": "1N"},+ "矻":{"골": "1"},+ "矼":{"강": "1N"},+ "矽":{"석": "1N"},+ "砂":{"사": "0N"},+ "砇":{"민": "N"},+ "砌":{"체": "1N"},+ "砏":{"분": "1N"},+ "砑":{"아": "1N"},+ "砒":{"비": "0N"},+ "砢":{"라": "1N"},+ "砥":{"지": "0N"},+ "砦":{"채": "0N"},+ "砧":{"침": "0N"},+ "砬":{"립": "0N"},+ "砭":{"폄": "1N"},+ "砰":{"팽": "1N"},+ "砲":{"포": "0N"},+ "破":{"파": "0E"},+ "硃":{"주": "1N"},+ "硅":{"규": "0N"},+ "硏":{"연": "0E"},+ "硜":{"갱": "1N"},+ "硝":{"초": "0N"},+ "硠":{"랑": "1N"},+ "硧":{"용": "1N"},+ "硨":{"차": "1N"},+ "硪":{"아": "N"},+ "硫":{"류": "0N", "유": "0"},+ "硬":{"경": "0E"},+ "确":{"학": "1N"},+ "硯":{"연": "0N"},+ "硼":{"붕": "0N"},+ "碁":{"기": "0N"},+ "碄":{"림": "N"},+ "碇":{"정": "0N"},+ "碌":{"녹": "0", "록": "0N"},+ "碍":{"애": "0N"},+ "碎":{"쇄": "0N"},+ "碏":{"작": "1N"},+ "碑":{"비": "0E"},+ "碓":{"대": "1N"},+ "碗":{"완": "0N"},+ "碟":{"설": "1N"},+ "碣":{"갈": "0N"},+ "碤":{"영": "1N"},+ "碧":{"벽": "0E"},+ "碨":{"외": "1N"},+ "碩":{"석": "0N"},+ "碬":{"하": "N"},+ "碭":{"탕": "1N"},+ "確":{"확": "0E"},+ "碻":{"확": "0N"},+ "碼":{"마": "0N"},+ "碾":{"년": "1N"},+ "磁":{"자": "0N"},+ "磅":{"방": "0N"},+ "磈":{"외": "1N"},+ "磊":{"뇌": "0", "뢰": "0N"},+ "磋":{"차": "0N"},+ "磎":{"계": "0N"},+ "磏":{"렴": "1N"},+ "磐":{"반": "0N"},+ "磑":{"애": "1N"},+ "磔":{"책": "1N"},+ "磕":{"개": "1N"},+ "磚":{"전": "1N"},+ "磠":{"뇨": "1"},+ "磧":{"적": "1N"},+ "磨":{"마": "0E"},+ "磪":{"최": "1N"},+ "磬":{"경": "0N"},+ "磯":{"기": "0N"},+ "磴":{"등": "1N"},+ "磵":{"간": "0N"},+ "磷":{"린": "1N"},+ "磺":{"광": "1N"},+ "磻":{"반": "0N", "번": "0N"},+ "磼":{"잡": "1N"},+ "磽":{"교": "1N"},+ "礁":{"초": "0N"},+ "礌":{"뢰": "1N"},+ "礎":{"초": "0E"},+ "礏":{"급": "1N"},+ "礑":{"당": "1N"},+ "礒":{"의": "1N"},+ "礖":{"여": "0N"},+ "礙":{"애": "1N"},+ "礧":{"뢰": "1N"},+ "礪":{"려": "0N", "여": "0"},+ "礫":{"력": "0N"},+ "礬":{"반": "0N"},+ "礭":{"확": "1N"},+ "礱":{"롱": "1N"},+ "示":{"시": "0E"},+ "礼":{"례": "N"},+ "社":{"사": "0E"},+ "祀":{"사": "0E"},+ "祁":{"기": "0N"},+ "祄":{"해": "N"},+ "祅":{"요": "1N"},+ "祆":{"천": "1N"},+ "祇":{"기": "0N"},+ "祈":{"기": "0E"},+ "祉":{"지": "0N"},+ "祊":{"팽": "1N"},+ "祐":{"우": "0N"},+ "祓":{"불": "1N"},+ "祔":{"부": "1N"},+ "祕":{"비": "1E"},+ "祖":{"조": "0E"},+ "祗":{"지": "0N"},+ "祘":{"산": "N"},+ "祚":{"조": "0N"},+ "祛":{"거": "0N"},+ "祜":{"호": "0N"},+ "祝":{"축": "0E"},+ "神":{"신": "0E"},+ "祟":{"수": "1N"},+ "祠":{"사": "0N"},+ "祢":{"니": "1N"},+ "祥":{"상": "0E"},+ "祧":{"조": "1N"},+ "票":{"표": "0E"},+ "祭":{"제": "0E"},+ "祹":{"도": "N"},+ "祺":{"기": "0N"},+ "祼":{"관": "1N"},+ "祿":{"녹": "0", "록": "0E"},+ "禀":{"품": "1"},+ "禁":{"금": "0E"},+ "禊":{"계": "1N"},+ "禋":{"인": "1N"},+ "禍":{"화": "0E"},+ "禎":{"정": "0N"},+ "福":{"복": "0E"},+ "禑":{"우": "0N"},+ "禔":{"시": "N", "제": "1N", "지": "N"},+ "禛":{"진": "N"},+ "禝":{"직": "1N"},+ "禦":{"어": "0N"},+ "禧":{"희": "0N"},+ "禨":{"기": "1N"},+ "禪":{"선": "0E"},+ "禫":{"담": "1N"},+ "禮":{"례": "0E", "예": "0"},+ "禰":{"니": "1N"},+ "禱":{"도": "0N"},+ "禳":{"양": "0N"},+ "禴":{"약": "1N"},+ "禹":{"우": "0N"},+ "禺":{"옹": "1N"},+ "离":{"리": "1N"},+ "禼":{"설": "N"},+ "禽":{"금": "0E"},+ "禾":{"화": "0E"},+ "禿":{"독": "0N"},+ "秀":{"수": "0E"},+ "私":{"사": "0E"},+ "秄":{"자": "N"},+ "秆":{"간": "1N"},+ "秉":{"병": "0N"},+ "秊":{"년": "0N", "연": "0"},+ "秋":{"추": "0E"},+ "科":{"과": "0E"},+ "秒":{"초": "0E"},+ "秕":{"비": "0N"},+ "秘":{"비": "0N"},+ "秞":{"유": "N"},+ "租":{"조": "0E"},+ "秢":{"령": "1N"},+ "秣":{"말": "1N"},+ "秤":{"칭": "0N"},+ "秦":{"진": "0N"},+ "秧":{"앙": "0N"},+ "秩":{"질": "0E"},+ "秪":{"지": "1N"},+ "秫":{"출": "1N"},+ "秬":{"거": "1N"},+ "秵":{"인": "N"},+ "秸":{"갈": "1N"},+ "移":{"이": "0E"},+ "稀":{"희": "0E"},+ "稁":{"고": "1N"},+ "稂":{"랑": "1N"},+ "稅":{"세": "0E"},+ "稈":{"간": "0N"},+ "稊":{"제": "1N"},+ "程":{"정": "0E"},+ "稌":{"도": "1N"},+ "稍":{"초": "0N"},+ "稔":{"임": "0N"},+ "稗":{"패": "0N"},+ "稘":{"기": "N"},+ "稙":{"직": "0N"},+ "稚":{"치": "0N"},+ "稜":{"능": "0", "릉": "0N"},+ "稞":{"과": "1N"},+ "稟":{"품": "0N"},+ "稠":{"조": "0N"},+ "稢":{"욱": "N"},+ "稧":{"설": "1N"},+ "種":{"종": "0E"},+ "稰":{"서": "N"},+ "稱":{"칭": "0E"},+ "稳":{"온": "N"},+ "稶":{"욱": "0N"},+ "稷":{"직": "0N"},+ "稹":{"진": "1N"},+ "稻":{"도": "0E"},+ "稼":{"가": "0N"},+ "稽":{"계": "0"},+ "稿":{"고": "0E"},+ "穀":{"곡": "0E"},+ "穂":{"수": "N"},+ "穅":{"강": "1N"},+ "穆":{"목": "0N"},+ "穉":{"치": "0N"},+ "穌":{"소": "N"},+ "積":{"적": "0E"},+ "穎":{"영": "0N"},+ "穗":{"수": "0N"},+ "穠":{"농": "1N"},+ "穡":{"색": "0N"},+ "穢":{"예": "0N"},+ "穦":{"빈": "N"},+ "穩":{"온": "0N"},+ "穫":{"확": "0E"},+ "穰":{"양": "0N"},+ "穴":{"혈": "0E"},+ "穵":{"알": "1N"},+ "究":{"구": "0E"},+ "穹":{"궁": "0N"},+ "空":{"공": "0E"},+ "穽":{"정": "0N"},+ "穾":{"요": "1N"},+ "穿":{"천": "0N"},+ "窀":{"둔": "1N"},+ "突":{"돌": "0E"},+ "窂":{"로": "1N"},+ "窃":{"절": "1"},+ "窄":{"착": "0N"},+ "窅":{"요": "1N"},+ "窆":{"폄": "1N"},+ "窈":{"요": "0N"},+ "窊":{"와": "1N"},+ "窒":{"질": "0N"},+ "窓":{"창": "0E"},+ "窕":{"조": "0N"},+ "窖":{"교": "1N"},+ "窗":{"창": "1N"},+ "窘":{"군": "0N"},+ "窙":{"효": "N"},+ "窛":{"구": "1"},+ "窟":{"굴": "0N"},+ "窠":{"과": "1N"},+ "窣":{"솔": "1N"},+ "窩":{"와": "0N"},+ "窪":{"와": "0N"},+ "窬":{"유": "1N"},+ "窮":{"궁": "0E"},+ "窯":{"요": "0N"},+ "窳":{"유": "1N"},+ "窶":{"구": "1N"},+ "窹":{"오": "1N"},+ "窺":{"규": "0N"},+ "窻":{"창": "1"},+ "窾":{"관": "1N"},+ "窿":{"륭": "1N"},+ "竄":{"찬": "0N"},+ "竅":{"규": "0N"},+ "竇":{"두": "0N"},+ "竈":{"조": "1N"},+ "竊":{"절": "0E"},+ "立":{"립": "0E", "입": "0"},+ "竗":{"묘": "0N"},+ "站":{"참": "0N"},+ "竜":{"룡": "N"},+ "竝":{"병": "0E"},+ "竟":{"경": "0E"},+ "章":{"장": "0E"},+ "竢":{"사": "1N"},+ "竣":{"준": "0N"},+ "童":{"동": "0E"},+ "竦":{"송": "1N"},+ "竪":{"수": "0N"},+ "竭":{"갈": "0N"},+ "端":{"단": "0E"},+ "竴":{"준": "N"},+ "競":{"경": "0E"},+ "竸":{"경": "1N"},+ "竹":{"죽": "0E"},+ "竺":{"축": "0N"},+ "竽":{"우": "1N"},+ "竿":{"간": "0N"},+ "笆":{"파": "1N"},+ "笈":{"급": "1N"},+ "笊":{"조": "1N"},+ "笌":{"아": "1N"},+ "笎":{"원": "N"},+ "笏":{"홀": "0N"},+ "笑":{"소": "0E"},+ "笒":{"금": "1N"},+ "笘":{"점": "1N"},+ "笙":{"생": "0N"},+ "笛":{"적": "0N"},+ "笞":{"태": "0N"},+ "笠":{"립": "0N", "입": "0"},+ "笥":{"사": "1N"},+ "符":{"부": "0E"},+ "笧":{"책": "1N"},+ "笨":{"분": "1N"},+ "第":{"제": "0E"},+ "笭":{"령": "0N"},+ "笯":{"노": "1N"},+ "笳":{"가": "1N"},+ "笵":{"범": "1N"},+ "笹":{"세": "0N"},+ "筅":{"선": "1N"},+ "筆":{"필": "0E"},+ "筈":{"괄": "1N"},+ "等":{"등": "0E"},+ "筋":{"근": "0N"},+ "筌":{"전": "0N"},+ "筍":{"순": "0N"},+ "筏":{"벌": "0N"},+ "筐":{"광": "0N"},+ "筑":{"축": "0N"},+ "筒":{"통": "0N"},+ "筓":{"계": "1"},+ "答":{"답": "0E"},+ "策":{"책": "0E"},+ "筟":{"부": "1N"},+ "筠":{"균": "0N"},+ "筥":{"거": "1N"},+ "筦":{"관": "1N"},+ "筧":{"견": "1N"},+ "筩":{"통": "1N"},+ "筬":{"성": "0N"},+ "筮":{"서": "0N"},+ "筱":{"소": "1N"},+ "筳":{"정": "1N"},+ "筵":{"연": "0N"},+ "筽":{"오": "0N"},+ "箇":{"개": "0N"},+ "箋":{"전": "0N"},+ "箍":{"고": "1N"},+ "箎":{"호": "1"},+ "箏":{"쟁": "0N"},+ "箒":{"추": "1"},+ "箔":{"박": "0N"},+ "箕":{"기": "0N"},+ "算":{"산": "0E"},+ "箙":{"복": "1N"},+ "箚":{"차": "0N"},+ "箜":{"공": "1N"},+ "箝":{"겸": "0N"},+ "箠":{"추": "1N"},+ "管":{"관": "0E"},+ "箭":{"전": "0N"},+ "箱":{"상": "0N"},+ "箴":{"잠": "0N"},+ "箸":{"저": "0N"},+ "箾":{"소": "1N"},+ "節":{"절": "0E"},+ "篁":{"황": "0N"},+ "範":{"범": "0E"},+ "篆":{"전": "0N"},+ "篇":{"편": "0E"},+ "築":{"축": "0E"},+ "篊":{"홍": "1N"},+ "篋":{"협": "1N"},+ "篌":{"후": "1N"},+ "篒":{"식": "0N"},+ "篔":{"운": "1N"},+ "篙":{"고": "1N"},+ "篛":{"약": "1N"},+ "篝":{"구": "1N"},+ "篠":{"소": "0N"},+ "篡":{"찬": "N"},+ "篤":{"독": "0E"},+ "篦":{"비": "1N"},+ "篩":{"사": "0N"},+ "篪":{"지": "1N"},+ "篳":{"필": "1N"},+ "篷":{"봉": "1N"},+ "篾":{"멸": "1N"},+ "簀":{"책": "1N"},+ "簇":{"족": "0N"},+ "簉":{"추": "1N"},+ "簋":{"궤": "1N"},+ "簏":{"록": "1N"},+ "簒":{"찬": "0N"},+ "簞":{"단": "0N"},+ "簟":{"점": "1N"},+ "簠":{"보": "1N"},+ "簡":{"간": "0E"},+ "簧":{"황": "0N"},+ "簪":{"잠": "0N"},+ "簫":{"소": "0N"},+ "簷":{"첨": "1N"},+ "簸":{"파": "1N"},+ "簽":{"첨": "0N"},+ "簾":{"렴": "0N", "염": "0"},+ "簿":{"부": "0E"},+ "籃":{"람": "0N"},+ "籌":{"주": "0N"},+ "籍":{"적": "0E"},+ "籐":{"등": "1N"},+ "籒":{"주": "1N"},+ "籔":{"수": "1N"},+ "籛":{"전": "1N"},+ "籜":{"탁": "1N"},+ "籟":{"뢰": "1N"},+ "籠":{"농": "0", "롱": "0N"},+ "籤":{"첨": "0N"},+ "籥":{"약": "1N"},+ "籧":{"거": "1N"},+ "籩":{"변": "1N"},+ "籬":{"리": "0N"},+ "籲":{"유": "1N"},+ "米":{"미": "0E"},+ "籾":{"인": "1"},+ "粁":{"천": "1"},+ "粃":{"비": "0N"},+ "粉":{"분": "0E"},+ "粍":{"모": "1"},+ "粒":{"립": "0N", "입": "0"},+ "粕":{"박": "0N"},+ "粗":{"조": "0N"},+ "粘":{"점": "0N"},+ "粟":{"속": "0E"},+ "粢":{"자": "1N"},+ "粤":{"월": "1N"},+ "粥":{"죽": "0N"},+ "粦":{"린": "1N"},+ "粧":{"장": "0E"},+ "粨":{"백": "1"},+ "粮":{"량": "0N"},+ "粱":{"량": "0N"},+ "粲":{"찬": "0N"},+ "粳":{"갱": "0N"},+ "粹":{"수": "0N"},+ "粼":{"린": "1N"},+ "粽":{"종": "1"},+ "精":{"정": "0E"},+ "糅":{"유": "1N"},+ "糆":{"면": "1"},+ "糊":{"호": "0N"},+ "糕":{"고": "1N"},+ "糖":{"당": "0E", "탕": "0N"},+ "糗":{"구": "1N"},+ "糙":{"조": "1N"},+ "糚":{"장": "1N"},+ "糜":{"미": "1N"},+ "糝":{"삼": "1N"},+ "糞":{"분": "0N"},+ "糟":{"조": "0N"},+ "糠":{"강": "0N"},+ "糢":{"모": "1"},+ "糥":{"나": "1"},+ "糧":{"량": "0E", "양": "0"},+ "糯":{"나": "1N"},+ "糱":{"얼": "N"},+ "糲":{"려": "1N"},+ "糴":{"적": "1N"},+ "糵":{"얼": "N"},+ "糶":{"조": "1N"},+ "糸":{"멱": "1", "사": "N"},+ "糺":{"규": "1N"},+ "系":{"계": "0E"},+ "糾":{"규": "0E"},+ "紀":{"기": "0E"},+ "紂":{"주": "0N"},+ "紃":{"순": "1N"},+ "約":{"약": "0E"},+ "紅":{"홍": "0E"},+ "紆":{"우": "0N"},+ "紇":{"흘": "0N"},+ "紈":{"환": "0N"},+ "紊":{"문": "0N"},+ "紋":{"문": "0N"},+ "納":{"납": "0E"},+ "紐":{"뉴": "0N", "유": "0"},+ "紓":{"서": "1N"},+ "純":{"순": "0E", "준": "N"},+ "紕":{"비": "1N"},+ "紗":{"사": "0N"},+ "紘":{"굉": "0N"},+ "紙":{"지": "0E"},+ "級":{"급": "0E"},+ "紛":{"분": "0E"},+ "紜":{"운": "1N"},+ "素":{"소": "0E"},+ "紡":{"방": "0N"},+ "索":{"삭": "0N", "색": "0E"},+ "紫":{"자": "0E"},+ "紬":{"주": "0N"},+ "紮":{"찰": "0N"},+ "累":{"누": "0", "루": "0E"},+ "細":{"세": "0E"},+ "紱":{"불": "1N"},+ "紲":{"설": "1N"},+ "紳":{"신": "0N"},+ "紵":{"저": "0N"},+ "紸":{"주": "N"},+ "紹":{"소": "0N"},+ "紺":{"감": "0N"},+ "絁":{"시": "N"},+ "終":{"종": "0E"},+ "絃":{"현": "0E"},+ "組":{"조": "0E"},+ "絅":{"경": "0N"},+ "絆":{"반": "0N"},+ "絉":{"술": "1N"},+ "絍":{"임": "1N"},+ "結":{"결": "0E"},+ "絑":{"주": "N"},+ "絕":{"절": "E"},+ "絖":{"광": "1N"},+ "絙":{"환": "1N"},+ "絛":{"조": "1N"},+ "絜":{"혈": "1N"},+ "絞":{"교": "0N"},+ "絡":{"락": "0E"},+ "絢":{"현": "0N"},+ "絣":{"병": "1N"},+ "給":{"급": "0E"},+ "絨":{"융": "0N"},+ "絩":{"조": "1N"},+ "絪":{"인": "0N"},+ "絮":{"서": "0N"},+ "絰":{"질": "1N"},+ "統":{"통": "0E"},+ "絲":{"사": "0E"},+ "絳":{"강": "0N"},+ "絵":{"회": "N"},+ "絶":{"절": "0N"},+ "絹":{"견": "0E"},+ "絺":{"치": "1N"},+ "絿":{"구": "0N"},+ "綃":{"초": "1N"},+ "綆":{"경": "1N"},+ "綎":{"정": "0N"},+ "綏":{"수": "0N"},+ "經":{"경": "0E"},+ "綘":{"봉": "1N"},+ "綜":{"종": "0N"},+ "綠":{"녹": "0", "록": "0E"},+ "綢":{"주": "0N"},+ "綣":{"권": "1N"},+ "綥":{"기": "1N"},+ "綦":{"기": "1N"},+ "綧":{"준": "1N"},+ "綩":{"원": "1"},+ "綫":{"선": "1N"},+ "綬":{"수": "0N"},+ "維":{"유": "0E"},+ "綮":{"계": "1N"},+ "綰":{"관": "1N"},+ "綱":{"강": "0E"},+ "網":{"망": "0N"},+ "綴":{"철": "0N"},+ "綵":{"채": "0N"},+ "綸":{"륜": "0N"},+ "綺":{"기": "0N"},+ "綻":{"탄": "0N"},+ "綽":{"작": "0N"},+ "綾":{"능": "0", "릉": "0N"},+ "綿":{"면": "0E"},+ "緄":{"곤": "1N"},+ "緇":{"치": "0N"},+ "緊":{"긴": "0E"},+ "緋":{"비": "0N"},+ "緌":{"유": "1N"},+ "緍":{"민": "1N"},+ "総":{"총": "N"},+ "緖":{"서": "0E"},+ "緗":{"상": "1N"},+ "緘":{"함": "0N"},+ "線":{"선": "0E"},+ "緜":{"면": "1N"},+ "緝":{"집": "0N"},+ "緞":{"단": "0N"},+ "締":{"체": "0N"},+ "緡":{"민": "0N"},+ "緣":{"연": "0E"},+ "緦":{"시": "1N"},+ "編":{"편": "0E"},+ "緩":{"완": "0E"},+ "緬":{"면": "0N"},+ "緯":{"위": "0E"},+ "練":{"련": "0E", "연": "0"},+ "緶":{"편": "1N"},+ "緹":{"제": "1N"},+ "緻":{"치": "0N"},+ "縃":{"서": "N"},+ "縈":{"영": "1N"},+ "縉":{"진": "0N"},+ "縊":{"액": "0N"},+ "縋":{"추": "1N"},+ "縐":{"추": "1N"},+ "縑":{"겸": "1N"},+ "縕":{"온": "0N"},+ "縗":{"최": "1N"},+ "縘":{"계": "1N"},+ "縛":{"박": "0N"},+ "縝":{"진": "0N"},+ "縞":{"호": "0N"},+ "縟":{"욕": "0N"},+ "縠":{"곡": "1N"},+ "縡":{"재": "0N"},+ "縢":{"등": "1N"},+ "縣":{"현": "0E"},+ "縫":{"봉": "0N"},+ "縮":{"축": "0E"},+ "縯":{"연": "0N"},+ "縱":{"종": "0E"},+ "縲":{"류": "1N"},+ "縳":{"견": "1N"},+ "縵":{"만": "1N"},+ "縷":{"누": "0", "루": "0N"},+ "縹":{"표": "1N"},+ "縻":{"미": "1N"},+ "總":{"총": "0E"},+ "績":{"적": "0E"},+ "繁":{"번": "0E"},+ "繃":{"붕": "0N"},+ "繄":{"예": "1N"},+ "繅":{"소": "1N"},+ "繆":{"무": "0N"},+ "繇":{"요": "0N"},+ "繈":{"강": "1N"},+ "繐":{"세": "1N"},+ "繒":{"증": "0N"},+ "織":{"직": "0E"},+ "繕":{"선": "0N"},+ "繖":{"산": "1N"},+ "繗":{"린": "1N"},+ "繙":{"번": "1N"},+ "繚":{"료": "1N"},+ "繞":{"요": "0N"},+ "繡":{"수": "0N"},+ "繢":{"궤": "1N"},+ "繩":{"승": "0N"},+ "繪":{"회": "0N"},+ "繫":{"계": "0E"},+ "繭":{"견": "0N"},+ "繯":{"현": "1N"},+ "繰":{"조": "0N"},+ "繶":{"억": "1N"},+ "繹":{"역": "0N"},+ "繼":{"계": "0E"},+ "繽":{"빈": "1N"},+ "繾":{"견": "1N"},+ "纁":{"훈": "1N"},+ "纂":{"찬": "0N"},+ "纇":{"뢰": "1N"},+ "纈":{"힐": "1N"},+ "纊":{"광": "1N"},+ "續":{"속": "0E"},+ "纍":{"류": "1N"},+ "纏":{"전": "0N"},+ "纓":{"영": "0N"},+ "纔":{"재": "1N"},+ "纖":{"섬": "0N"},+ "纘":{"찬": "0N"},+ "纛":{"독": "0N"},+ "纜":{"람": "0N"},+ "缶":{"부": "0N"},+ "缷":{"사": "1"},+ "缸":{"항": "0N"},+ "缺":{"결": "0E"},+ "缾":{"병": "1N"},+ "缿":{"항": "1N"},+ "罃":{"앵": "1N"},+ "罄":{"경": "1N"},+ "罅":{"하": "1N"},+ "罇":{"준": "1N"},+ "罋":{"옹": "1N"},+ "罌":{"앵": "0N"},+ "罍":{"뢰": "1N"},+ "罎":{"담": "1N"},+ "罐":{"관": "0N"},+ "罔":{"망": "0E"},+ "罕":{"한": "0N"},+ "罘":{"부": "1N"},+ "罝":{"저": "1N"},+ "罟":{"고": "1N"},+ "罠":{"민": "1N"},+ "罡":{"강": "1N"},+ "罣":{"괘": "1N"},+ "罦":{"부": "1N"},+ "罨":{"엄": "1N"},+ "罪":{"죄": "0E"},+ "罫":{"괘": "0N"},+ "置":{"치": "0E"},+ "罰":{"벌": "0E"},+ "署":{"서": "0E"},+ "罵":{"매": "0N"},+ "罷":{"파": "0E"},+ "罸":{"벌": "1N"},+ "罹":{"리": "0N", "이": "0"},+ "罼":{"필": "1N"},+ "罽":{"계": "1N"},+ "罾":{"증": "1N"},+ "羂":{"견": "1N"},+ "羅":{"나": "0", "라": "0E"},+ "羆":{"비": "1N"},+ "羇":{"기": "1N"},+ "羈":{"기": "0N"},+ "羊":{"양": "0E"},+ "羌":{"강": "0N"},+ "美":{"미": "0E"},+ "羔":{"고": "0N"},+ "羖":{"고": "1N"},+ "羗":{"강": "1"},+ "羘":{"장": "1N"},+ "羚":{"령": "0N", "영": "0"},+ "羝":{"저": "1N"},+ "羞":{"수": "0N"},+ "羡":{"이": "N"},+ "群":{"군": "0E"},+ "羨":{"선": "0N"},+ "義":{"의": "0E"},+ "羫":{"강": "1N"},+ "羯":{"갈": "1N"},+ "羲":{"희": "0N"},+ "羶":{"전": "1N"},+ "羸":{"리": "0N"},+ "羹":{"갱": "0N"},+ "羽":{"우": "0E"},+ "羿":{"예": "N"},+ "翁":{"옹": "0E"},+ "翅":{"시": "0N"},+ "翊":{"익": "0N"},+ "翌":{"익": "0N"},+ "翎":{"령": "0N"},+ "習":{"습": "0E"},+ "翔":{"상": "0N"},+ "翕":{"흡": "0N"},+ "翖":{"흡": "1N"},+ "翛":{"소": "1N"},+ "翟":{"적": "0N"},+ "翠":{"취": "0N"},+ "翡":{"비": "0N"},+ "翣":{"삽": "1N"},+ "翤":{"시": "1N"},+ "翦":{"전": "1N"},+ "翩":{"편": "0N"},+ "翫":{"완": "0N"},+ "翬":{"휘": "1N"},+ "翮":{"핵": "1N"},+ "翰":{"한": "0N"},+ "翳":{"예": "1N"},+ "翹":{"교": "0N"},+ "翺":{"고": "1N"},+ "翻":{"번": "1N"},+ "翼":{"익": "0E"},+ "翾":{"현": "1N"},+ "耀":{"요": "0N"},+ "老":{"노": "0", "로": "0E"},+ "考":{"고": "0E"},+ "耄":{"모": "1N"},+ "者":{"자": "0E"},+ "耆":{"기": "0N"},+ "耇":{"구": "N"},+ "耈":{"구": "N"},+ "耉":{"구": "0"},+ "而":{"이": "0E"},+ "耐":{"내": "0E"},+ "耑":{"단": "1N"},+ "耒":{"뢰": "1N"},+ "耔":{"자": "1N"},+ "耕":{"경": "0E"},+ "耖":{"초": "1N"},+ "耗":{"모": "0N"},+ "耘":{"운": "0N"},+ "耙":{"파": "1N"},+ "耞":{"가": "1N"},+ "耡":{"서": "1N"},+ "耦":{"우": "1N"},+ "耨":{"누": "1N"},+ "耬":{"루": "1N"},+ "耭":{"기": "0N"},+ "耰":{"우": "1N"},+ "耳":{"이": "0E"},+ "耶":{"야": "0E"},+ "耽":{"탐": "0N"},+ "耿":{"경": "0N"},+ "聃":{"담": "0N"},+ "聆":{"령": "0N", "영": "0"},+ "聈":{"유": "N"},+ "聊":{"료": "0N"},+ "聒":{"괄": "1N"},+ "聕":{"호": "1N"},+ "聖":{"성": "0EN"},+ "聘":{"빙": "0E"},+ "聚":{"취": "0N"},+ "聞":{"문": "0E"},+ "聡":{"총": "N"},+ "聯":{"련": "0E", "연": "0"},+ "聰":{"총": "0E"},+ "聱":{"오": "1N"},+ "聲":{"성": "0E"},+ "聳":{"용": "0N"},+ "聵":{"외": "1N"},+ "聶":{"섭": "1N"},+ "職":{"직": "0E"},+ "聽":{"청": "0E"},+ "聾":{"농": "0", "롱": "0N"},+ "聿":{"율": "0N"},+ "肄":{"이": "0N"},+ "肅":{"숙": "0E"},+ "肆":{"사": "0N"},+ "肇":{"조": "0N"},+ "肉":{"육": "0E"},+ "肋":{"늑": "0", "륵": "0N"},+ "肌":{"기": "0N"},+ "肓":{"황": "1N"},+ "肖":{"초": "0E"},+ "肘":{"주": "1"},+ "肚":{"두": "1N"},+ "肛":{"항": "0N"},+ "肝":{"간": "0E"},+ "股":{"고": "0N"},+ "肢":{"지": "0N"},+ "肥":{"비": "0E"},+ "肦":{"분": "1N"},+ "肩":{"견": "0E"},+ "肪":{"방": "0N"},+ "肫":{"순": "1N"},+ "肭":{"눌": "1N"},+ "肯":{"긍": "0E"},+ "肱":{"굉": "0N"},+ "育":{"육": "0E"},+ "肴":{"효": "0N"},+ "肵":{"기": "1N"},+ "肺":{"폐": "0E"},+ "胃":{"위": "0E"},+ "胄":{"주": "0"},+ "胆":{"단": "1N"},+ "胊":{"구": "1N"},+ "背":{"배": "0E"},+ "胎":{"태": "0N"},+ "胕":{"부": "1N", "주": "N"},+ "胖":{"반": "1N"},+ "胙":{"조": "1N"},+ "胚":{"배": "0N"},+ "胛":{"갑": "0N"},+ "胜":{"성": "N", "정": "N"},+ "胞":{"포": "0E"},+ "胠":{"거": "1N"},+ "胡":{"호": "0E"},+ "胤":{"윤": "0N"},+ "胥":{"서": "0N"},+ "胯":{"고": "1N"},+ "胱":{"광": "0N"},+ "胴":{"동": "0N"},+ "胷":{"흉": "1N"},+ "胸":{"흉": "0E"},+ "能":{"능": "0E"},+ "胾":{"자": "1N"},+ "脂":{"지": "0N"},+ "脅":{"협": "0E"},+ "脆":{"취": "0N"},+ "脇":{"협": "0N"},+ "脈":{"맥": "0E"},+ "脉":{"맥": "1"},+ "脊":{"척": "0N"},+ "脖":{"발": "1N"},+ "脗":{"민": "N"},+ "脘":{"완": "0N"},+ "脚":{"각": "0E"},+ "脛":{"경": "0N"},+ "脣":{"순": "0E"},+ "脤":{"신": "1N"},+ "脧":{"최": "1N"},+ "脩":{"수": "0N"},+ "脫":{"탈": "0E", "태": "N"},+ "脯":{"포": "0N"},+ "脰":{"두": "1N"},+ "脹":{"창": "0N"},+ "脺":{"수": "1N"},+ "脾":{"비": "0N"},+ "腁":{"변": "1N"},+ "腆":{"전": "1N"},+ "腊":{"석": "1N"},+ "腋":{"액": "0N"},+ "腎":{"신": "0N"},+ "腐":{"부": "0E"},+ "腑":{"부": "0N"},+ "腒":{"거": "1N"},+ "腓":{"비": "1N"},+ "腔":{"강": "0N"},+ "腕":{"완": "0N"},+ "腠":{"주": "1N"},+ "腤":{"암": "1N"},+ "腥":{"성": "0N"},+ "腦":{"뇌": "0E"},+ "腫":{"종": "0N"},+ "腭":{"악": "1N"},+ "腰":{"요": "0E"},+ "腱":{"건": "0N"},+ "腴":{"유": "1N"},+ "腶":{"단": "1N"},+ "腷":{"픽": "1N"},+ "腸":{"장": "0E"},+ "腹":{"복": "0E"},+ "腺":{"선": "0N"},+ "腿":{"퇴": "0N"},+ "膀":{"방": "0N"},+ "膂":{"려": "1N"},+ "膃":{"올": "1N"},+ "膄":{"수": "1N"},+ "膆":{"소": "1N"},+ "膈":{"격": "0N"},+ "膊":{"박": "0N"},+ "膋":{"료": "1N"},+ "膏":{"고": "0N"},+ "膚":{"부": "0N"},+ "膜":{"막": "0N"},+ "膝":{"슬": "0N"},+ "膞":{"전": "1N"},+ "膠":{"교": "0N"},+ "膣":{"질": "0N"},+ "膨":{"팽": "0N"},+ "膩":{"니": "1N"},+ "膰":{"번": "1N"},+ "膳":{"선": "0N"},+ "膴":{"무": "1N"},+ "膵":{"췌": "0N"},+ "膸":{"수": "1N"},+ "膹":{"분": "1N"},+ "膺":{"응": "0N"},+ "膽":{"담": "0N"},+ "膾":{"회": "0N"},+ "膿":{"농": "0N"},+ "臀":{"둔": "0N"},+ "臂":{"비": "0N"},+ "臆":{"억": "0N"},+ "臊":{"조": "1N"},+ "臍":{"제": "0N"},+ "臏":{"빈": "1N"},+ "臑":{"노": "1N"},+ "臘":{"납": "0", "랍": "0N"},+ "臙":{"연": "1N"},+ "臚":{"려": "1N"},+ "臝":{"라": "1N"},+ "臟":{"장": "0E"},+ "臠":{"련": "1N"},+ "臣":{"신": "0E"},+ "臥":{"와": "0E"},+ "臧":{"장": "0N"},+ "臨":{"림": "0E", "임": "0"},+ "自":{"자": "0E"},+ "臬":{"얼": "1N"},+ "臭":{"취": "0E"},+ "至":{"지": "0E"},+ "致":{"치": "0E"},+ "臶":{"천": "1N"},+ "臺":{"대": "0E"},+ "臻":{"진": "0N"},+ "臼":{"구": "0N"},+ "臾":{"유": "0N"},+ "舁":{"여": "1N"},+ "舂":{"용": "1N"},+ "舃":{"석": "1N", "작": "N"},+ "舅":{"구": "0N"},+ "與":{"여": "0E"},+ "興":{"흥": "0E"},+ "舊":{"구": "0E"},+ "舌":{"설": "0E"},+ "舍":{"사": "0E"},+ "舐":{"지": "1N"},+ "舒":{"서": "0N"},+ "舖":{"포": "1"},+ "舘":{"관": "N"},+ "舛":{"천": "0N"},+ "舜":{"순": "0N"},+ "舞":{"무": "0E"},+ "舟":{"주": "0E"},+ "舡":{"강": "0N"},+ "航":{"항": "0E"},+ "舫":{"방": "0N"},+ "般":{"반": "0E"},+ "舳":{"축": "1N"},+ "舵":{"타": "0N"},+ "舶":{"박": "0N"},+ "舷":{"현": "0N"},+ "舸":{"가": "1N"},+ "船":{"선": "0E"},+ "舽":{"방": "1N"},+ "艀":{"부": "0N"},+ "艅":{"여": "0N"},+ "艇":{"정": "0N"},+ "艑":{"편": "1N"},+ "艘":{"소": "1N"},+ "艙":{"창": "0N"},+ "艚":{"조": "1N"},+ "艟":{"동": "1N"},+ "艤":{"의": "0N"},+ "艦":{"함": "0N"},+ "艨":{"몽": "1N"},+ "艪":{"로": "1N"},+ "艫":{"로": "1N"},+ "艮":{"간": "0N"},+ "良":{"량": "0E", "양": "0"},+ "艱":{"간": "0N"},+ "色":{"색": "0E"},+ "艴":{"불": "1N"},+ "艶":{"염": "0N"},+ "艷":{"염": "N"},+ "艸":{"초": "0N"},+ "艾":{"애": "0N", "예": "N"},+ "芃":{"봉": "N"},+ "芊":{"천": "1N"},+ "芋":{"우": "0N", "후": "N"},+ "芍":{"작": "0N"},+ "芎":{"궁": "0N"},+ "芐":{"호": "N"},+ "芒":{"망": "0N"},+ "芔":{"훼": "1N"},+ "芘":{"비": "1N"},+ "芙":{"부": "0N"},+ "芚":{"둔": "0N"},+ "芝":{"지": "0N"},+ "芟":{"삼": "0N"},+ "芡":{"검": "1N"},+ "芢":{"인": "1N"},+ "芣":{"부": "1N"},+ "芥":{"개": "0N"},+ "芦":{"호": "0N"},+ "芧":{"서": "1N"},+ "芨":{"급": "1N"},+ "芩":{"금": "0N"},+ "芪":{"기": "1N"},+ "芫":{"원": "1N"},+ "芬":{"분": "0N"},+ "芭":{"파": "0N"},+ "芮":{"예": "0N"},+ "芯":{"심": "0N"},+ "芰":{"기": "1N"},+ "花":{"화": "0E"},+ "芳":{"방": "0E"},+ "芷":{"지": "0N"},+ "芸":{"예": "N", "운": "0N"},+ "芹":{"근": "0N"},+ "芻":{"추": "0N"},+ "芼":{"모": "0N"},+ "芽":{"아": "0E"},+ "芾":{"비": "1N"},+ "芿":{"잉": "0N"},+ "苅":{"예": "1"},+ "苑":{"원": "0N"},+ "苒":{"염": "0N"},+ "苓":{"령": "1N"},+ "苔":{"태": "0N"},+ "苕":{"초": "0N"},+ "苗":{"묘": "0E"},+ "苛":{"가": "0N"},+ "苜":{"목": "1N"},+ "苞":{"포": "0N"},+ "苟":{"구": "0E"},+ "苠":{"민": "1N"},+ "苡":{"이": "0N"},+ "苣":{"거": "1N"},+ "若":{"야": "0N", "약": "0E"},+ "苦":{"고": "0E"},+ "苧":{"저": "0N"},+ "苩":{"백": "N"},+ "苫":{"점": "1N"},+ "英":{"영": "0E"},+ "苳":{"동": "1N"},+ "苴":{"저": "1N"},+ "苹":{"평": "1N"},+ "苺":{"매": "1N"},+ "苻":{"부": "1N"},+ "苽":{"고": "0N"},+ "苾":{"필": "0N"},+ "苿":{"미": "1N"},+ "茀":{"불": "1N"},+ "茁":{"줄": "0N"},+ "茂":{"무": "0E"},+ "范":{"범": "0N"},+ "茄":{"가": "0N"},+ "茅":{"모": "0N"},+ "茈":{"자": "1N"},+ "茉":{"말": "0N"},+ "茗":{"명": "0N"},+ "茛":{"간": "1N"},+ "茜":{"천": "1N"},+ "茝":{"채": "1N"},+ "茣":{"오": "1N"},+ "茤":{"다": "N"},+ "茥":{"규": "N"},+ "茨":{"자": "0N"},+ "茪":{"광": "1N"},+ "茫":{"망": "0E"},+ "茯":{"복": "0N"},+ "茱":{"수": "0N"},+ "茲":{"자": "1E"},+ "茳":{"강": "1N"},+ "茴":{"회": "0N"},+ "茵":{"인": "0N"},+ "茶":{"다": "0E", "차": "0N"},+ "茸":{"용": "0N"},+ "茹":{"여": "0N"},+ "茼":{"동": "1N"},+ "荀":{"순": "0N"},+ "荃":{"전": "1N"},+ "荇":{"행": "0N"},+ "草":{"초": "0E"},+ "荊":{"형": "0N"},+ "荏":{"임": "0N"},+ "荐":{"천": "1N"},+ "荑":{"이": "0N"},+ "荒":{"황": "0E"},+ "荣":{"영": "N"},+ "荳":{"두": "0N"},+ "荷":{"하": "0E"},+ "荺":{"윤": "N"},+ "荻":{"적": "0N"},+ "莂":{"별": "N"},+ "莅":{"리": "1N"},+ "莉":{"리": "0N"},+ "莊":{"장": "0E"},+ "莎":{"사": "0N"},+ "莒":{"거": "1N"},+ "莓":{"매": "1N"},+ "莖":{"경": "0N"},+ "莘":{"신": "0N"},+ "莚":{"연": "1N"},+ "莛":{"정": "1N"},+ "莝":{"좌": "1N"},+ "莞":{"완": "0N"},+ "莟":{"함": "1N"},+ "莠":{"유": "1N"},+ "莢":{"협": "0N"},+ "莨":{"랑": "1N"},+ "莩":{"부": "0N"},+ "莪":{"아": "0N"},+ "莫":{"막": "0E"},+ "莽":{"망": "0N"},+ "莾":{"망": "1"},+ "莿":{"자": "1N"},+ "菀":{"울": "N"},+ "菁":{"청": "0N"},+ "菂":{"적": "1N"},+ "菅":{"관": "0N"},+ "菉":{"녹": "0", "록": "0N"},+ "菊":{"국": "0E"},+ "菌":{"균": "0E"},+ "菑":{"치": "1N"},+ "菓":{"과": "0N"},+ "菔":{"복": "1N"},+ "菖":{"창": "0N"},+ "菘":{"숭": "1N"},+ "菜":{"채": "0E"},+ "菟":{"도": "1N"},+ "菠":{"파": "1N"},+ "菡":{"함": "1N"},+ "菩":{"보": "0N"},+ "菫":{"근": "0N"},+ "華":{"화": "0E"},+ "菰":{"고": "0N"},+ "菱":{"능": "0", "릉": "0N"},+ "菲":{"비": "0N"},+ "菴":{"암": "0N"},+ "菶":{"봉": "1N"},+ "菹":{"저": "0N"},+ "菻":{"름": "N"},+ "菽":{"숙": "0N"},+ "萃":{"췌": "0N"},+ "萄":{"도": "0N"},+ "萆":{"비": "1N"},+ "萇":{"장": "1N"},+ "萊":{"래": "0N"},+ "萋":{"처": "1N"},+ "萌":{"맹": "0N"},+ "萍":{"평": "0N"},+ "萎":{"위": "0N"},+ "萩":{"추": "0N"},+ "萬":{"만": "0E"},+ "萱":{"훤": "0N"},+ "萵":{"와": "1N"},+ "萸":{"유": "0N"},+ "萹":{"편": "1N"},+ "萼":{"악": "1N"},+ "落":{"낙": "0", "락": "0E"},+ "葆":{"보": "1N"},+ "葉":{"섭": "0N", "엽": "0E"},+ "葊":{"암": "1N"},+ "葑":{"풍": "1"},+ "著":{"저": "0E"},+ "葚":{"심": "1N"},+ "葛":{"갈": "0N"},+ "葡":{"포": "0N"},+ "董":{"동": "0N"},+ "葦":{"위": "0N"},+ "葩":{"파": "1N"},+ "葪":{"계": "1"},+ "葫":{"호": "0N"},+ "葬":{"장": "0E"},+ "葭":{"가": "1N"},+ "葯":{"약": "0N"},+ "葰":{"준": "N"},+ "葱":{"총": "1N"},+ "葳":{"위": "1N"},+ "葵":{"규": "0N"},+ "葷":{"훈": "1N"},+ "葺":{"즙": "0N"},+ "蒂":{"체": "1N"},+ "蒐":{"수": "0N"},+ "蒑":{"은": "N"},+ "蒔":{"시": "0N"},+ "蒙":{"몽": "0E"},+ "蒜":{"산": "0N"},+ "蒟":{"구": "1N"},+ "蒡":{"방": "0N"},+ "蒨":{"천": "1N"},+ "蒭":{"추": "1N"},+ "蒯":{"괴": "1N"},+ "蒲":{"포": "0N"},+ "蒴":{"삭": "1N"},+ "蒸":{"증": "0E"},+ "蒹":{"겸": "1N"},+ "蒺":{"질": "1N"},+ "蒻":{"약": "0N"},+ "蒼":{"창": "0E"},+ "蒽":{"은": "N"},+ "蒿":{"호": "0N"},+ "蓀":{"손": "0N"},+ "蓁":{"진": "1N"},+ "蓂":{"명": "0N"},+ "蓄":{"축": "0E"},+ "蓆":{"석": "0N"},+ "蓉":{"용": "0N"},+ "蓊":{"옹": "1N"},+ "蓋":{"개": "0E"},+ "蓍":{"시": "0N"},+ "蓏":{"라": "N"},+ "蓐":{"욕": "1N"},+ "蓑":{"사": "0N"},+ "蓓":{"배": "1N"},+ "蓖":{"비": "1N"},+ "蓚":{"수": "0N"},+ "蓬":{"봉": "0N"},+ "蓭":{"암": "1N"},+ "蓮":{"련": "0E", "연": "0"},+ "蓯":{"총": "1N"},+ "蓱":{"평": "1N"},+ "蓴":{"순": "0N"},+ "蓺":{"예": "N"},+ "蓼":{"료": "0N", "요": "0"},+ "蓽":{"필": "1N"},+ "蔀":{"부": "1N"},+ "蔆":{"릉": "1N"},+ "蔎":{"설": "N"},+ "蔑":{"멸": "0N"},+ "蔓":{"만": "0N"},+ "蔔":{"복": "0N"},+ "蔕":{"체": "1N"},+ "蔗":{"자": "0N"},+ "蔘":{"삼": "0N"},+ "蔚":{"울": "0N"},+ "蔞":{"루": "0N"},+ "蔟":{"주": "1N"},+ "蔡":{"채": "0N"},+ "蔣":{"장": "0N"},+ "蔥":{"총": "0N"},+ "蔦":{"조": "1N"},+ "蔪":{"점": "1N"},+ "蔬":{"소": "0E"},+ "蔭":{"음": "0N"},+ "蔯":{"진": "0N"},+ "蔰":{"호": "N"},+ "蔽":{"폐": "0E"},+ "蔿":{"위": "0N"},+ "蕁":{"담": "0N"},+ "蕃":{"번": "0N"},+ "蕆":{"천": "1N"},+ "蕉":{"초": "0N"},+ "蕊":{"예": "1N"},+ "蕋":{"예": "1"},+ "蕎":{"교": "0N"},+ "蕓":{"운": "0N"},+ "蕕":{"유": "1N"},+ "蕖":{"거": "1N"},+ "蕗":{"로": "N"},+ "蕘":{"요": "1N"},+ "蕙":{"혜": "0N"},+ "蕞":{"체": "1"},+ "蕡":{"분": "1N"},+ "蕣":{"순": "0N"},+ "蕤":{"유": "1N"},+ "蕨":{"궐": "0N"},+ "蕩":{"탕": "0N"},+ "蕪":{"무": "0N"},+ "蕫":{"동": "1N"},+ "蕭":{"소": "0N"},+ "蕸":{"하": "N"},+ "蕺":{"즙": "1N"},+ "蕾":{"뢰": "1N"},+ "薀":{"온": "1N"},+ "薄":{"박": "0E"},+ "薆":{"애": "1N"},+ "薇":{"미": "0N"},+ "薉":{"예": "1N"},+ "薊":{"계": "1N"},+ "薌":{"향": "1N"},+ "薏":{"의": "0N"},+ "薑":{"강": "0N"},+ "薔":{"장": "0N"},+ "薗":{"원": "1N"},+ "薙":{"치": "1N"},+ "薛":{"설": "0N"},+ "薝":{"담": "1N"},+ "薤":{"해": "1N"},+ "薥":{"촉": "1N"},+ "薦":{"천": "0E"},+ "薨":{"훙": "0N"},+ "薩":{"살": "0N"},+ "薪":{"신": "0N"},+ "薫":{"훈": "N"},+ "薯":{"서": "0N"},+ "薰":{"훈": "0N"},+ "薺":{"제": "0N"},+ "藁":{"고": "0N"},+ "藇":{"서": "N"},+ "藉":{"자": "0N"},+ "藍":{"남": "0", "람": "0N"},+ "藎":{"신": "0N"},+ "藏":{"장": "0E"},+ "藐":{"묘": "1N"},+ "藕":{"우": "0N"},+ "藜":{"려": "0N"},+ "藝":{"예": "0E"},+ "藤":{"등": "0N"},+ "藥":{"약": "0E"},+ "藩":{"번": "0N"},+ "藪":{"수": "0N"},+ "藷":{"저": "0N"},+ "藹":{"애": "1N"},+ "藺":{"린": "0N", "인": "0"},+ "藻":{"조": "0N"},+ "藽":{"친": "1"},+ "藿":{"곽": "0N"},+ "蘀":{"탁": "1N"},+ "蘂":{"예": "0N"},+ "蘄":{"기": "1N"},+ "蘆":{"노": "0", "로": "0N"},+ "蘇":{"소": "0E"},+ "蘊":{"온": "0N"},+ "蘋":{"빈": "1N"},+ "蘖":{"얼": "0N"},+ "蘗":{"벽": "0N"},+ "蘘":{"양": "1N"},+ "蘚":{"선": "0N"},+ "蘟":{"은": "N"},+ "蘢":{"롱": "1N"},+ "蘧":{"거": "1N"},+ "蘩":{"번": "1N"},+ "蘪":{"미": "N"},+ "蘭":{"난": "0", "란": "0E"},+ "蘯":{"탕": "1N"},+ "蘼":{"미": "1N"},+ "蘿":{"나": "0", "라": "0N"},+ "虁":{"기": "1"},+ "虎":{"호": "0E"},+ "虐":{"학": "0N"},+ "虓":{"효": "1N"},+ "虔":{"건": "0N"},+ "處":{"처": "0E"},+ "虛":{"허": "0E"},+ "虜":{"노": "0", "로": "0N"},+ "虞":{"우": "0N"},+ "號":{"호": "0E"},+ "虧":{"휴": "0N"},+ "虫":{"충": "N", "훼": "1"},+ "虬":{"규": "1"},+ "虯":{"규": "1N"},+ "虱":{"슬": "1N"},+ "虸":{"자": "1N"},+ "虹":{"홍": "0N"},+ "虺":{"훼": "1N"},+ "虻":{"맹": "1N"},+ "蚊":{"문": "0N"},+ "蚋":{"예": "1N"},+ "蚌":{"방": "0N"},+ "蚍":{"비": "1N"},+ "蚓":{"인": "0N"},+ "蚕":{"천": "1"},+ "蚣":{"공": "0N"},+ "蚤":{"조": "0N"},+ "蚨":{"부": "1N"},+ "蚩":{"치": "0N"},+ "蚪":{"두": "1N"},+ "蚯":{"구": "1N"},+ "蚰":{"유": "1N"},+ "蚱":{"책": "1N"},+ "蚴":{"유": "1N"},+ "蛀":{"주": "1N"},+ "蛅":{"점": "1N"},+ "蛆":{"저": "1N"},+ "蛇":{"사": "0E"},+ "蛉":{"령": "1N"},+ "蛋":{"단": "0N"},+ "蛔":{"회": "0N"},+ "蛙":{"와": "0N"},+ "蛛":{"주": "0N"},+ "蛞":{"활": "1N"},+ "蛟":{"교": "0N"},+ "蛣":{"길": "1N"},+ "蛤":{"합": "0N"},+ "蛩":{"공": "1N"},+ "蛬":{"공": "1N"},+ "蛭":{"질": "0N"},+ "蛸":{"소": "1N"},+ "蛹":{"용": "1N"},+ "蛻":{"세": "1N"},+ "蛾":{"아": "0N"},+ "蜀":{"촉": "0N"},+ "蜂":{"봉": "0E"},+ "蜃":{"신": "0N"},+ "蜆":{"현": "1N"},+ "蜈":{"오": "0N"},+ "蜉":{"부": "1N"},+ "蜊":{"리": "1N"},+ "蜋":{"랑": "1N"},+ "蜑":{"단": "1N"},+ "蜘":{"지": "0N"},+ "蜚":{"비": "0N"},+ "蜜":{"밀": "0E"},+ "蜝":{"기": "1N"},+ "蜡":{"사": "1N"},+ "蜥":{"석": "1N"},+ "蜨":{"접": "1N"},+ "蜩":{"조": "1N"},+ "蜴":{"척": "1N"},+ "蜵":{"연": "1N"},+ "蜷":{"권": "1N"},+ "蜺":{"예": "1N"},+ "蜻":{"청": "1N"},+ "蜿":{"원": "1N"},+ "蝀":{"동": "1N"},+ "蝌":{"과": "1N"},+ "蝎":{"갈": "0N"},+ "蝕":{"식": "0N"},+ "蝗":{"황": "0N"},+ "蝙":{"편": "1N"},+ "蝟":{"위": "0N"},+ "蝠":{"복": "1N"},+ "蝤":{"유": "1N"},+ "蝥":{"모": "1N"},+ "蝦":{"하": "0N"},+ "蝨":{"슬": "0N"},+ "蝮":{"복": "1N"},+ "蝴":{"호": "0N"},+ "蝶":{"접": "0E"},+ "蝸":{"와": "0N"},+ "螂":{"랑": "0N"},+ "螃":{"방": "1N"},+ "螌":{"반": "1N"},+ "融":{"융": "0N"},+ "螘":{"의": "1N"},+ "螞":{"마": "1N"},+ "螟":{"명": "0N"},+ "螢":{"형": "0E"},+ "螣":{"등": "1N"},+ "螭":{"리": "1N"},+ "螳":{"당": "0N"},+ "螴":{"진": "1N"},+ "螺":{"나": "0", "라": "0N"},+ "螻":{"루": "1N"},+ "螽":{"종": "1N"},+ "蟀":{"솔": "1N"},+ "蟄":{"칩": "0N"},+ "蟇":{"마": "1N"},+ "蟊":{"모": "1N"},+ "蟋":{"실": "1N"},+ "蟒":{"망": "1"},+ "蟚":{"팽": "1N"},+ "蟛":{"팽": "1N"},+ "蟠":{"반": "0N"},+ "蟣":{"기": "1N"},+ "蟬":{"선": "0N"},+ "蟯":{"요": "0N"},+ "蟲":{"충": "0E"},+ "蟷":{"당": "1N"},+ "蟹":{"해": "0N"},+ "蟻":{"의": "0N"},+ "蟾":{"섬": "0N"},+ "蠅":{"승": "0N"},+ "蠍":{"갈": "1N"},+ "蠑":{"영": "1N"},+ "蠕":{"연": "1N"},+ "蠟":{"납": "0", "랍": "0N"},+ "蠡":{"려": "1N"},+ "蠢":{"준": "0N"},+ "蠣":{"려": "0N"},+ "蠱":{"고": "0N"},+ "蠲":{"견": "1N"},+ "蠶":{"잠": "0N"},+ "蠹":{"두": "1N"},+ "蠻":{"만": "0N"},+ "血":{"혈": "0E"},+ "衄":{"뉵": "1N"},+ "衆":{"중": "0E"},+ "衊":{"멸": "1N"},+ "行":{"항": "0N", "행": "0E"},+ "衍":{"연": "0N"},+ "衎":{"간": "1N"},+ "衒":{"현": "0N"},+ "術":{"술": "0E"},+ "街":{"가": "0E"},+ "衙":{"아": "0N"},+ "衛":{"위": "0E"},+ "衝":{"충": "0E"},+ "衞":{"위": "1N"},+ "衡":{"형": "0E"},+ "衢":{"구": "0N"},+ "衣":{"의": "0E"},+ "表":{"표": "0E"},+ "衫":{"삼": "0N"},+ "衮":{"곤": "1N"},+ "衰":{"쇠": "0"},+ "衲":{"납": "0N"},+ "衷":{"충": "0N"},+ "衽":{"임": "1N"},+ "衾":{"금": "0N"},+ "衿":{"금": "0N"},+ "袁":{"원": "0N"},+ "袂":{"몌": "0N"},+ "袈":{"가": "0N"},+ "袋":{"대": "0N"},+ "袍":{"포": "0N"},+ "袒":{"단": "0N"},+ "袖":{"수": "0N"},+ "袗":{"진": "0N"},+ "袛":{"저": "1N"},+ "袝":{"부": "1N"},+ "袞":{"곤": "0N"},+ "袢":{"번": "1N"},+ "袪":{"거": "1N"},+ "被":{"피": "0E"},+ "袴":{"고": "0N"},+ "裀":{"인": "1N"},+ "裁":{"재": "0E"},+ "裂":{"렬": "0E", "열": "0"},+ "装":{"장": "1"},+ "裊":{"뇨": "1"},+ "裍":{"곤": "1N"},+ "裏":{"리": "0E", "이": "0"},+ "裒":{"부": "1N"},+ "裔":{"예": "0N"},+ "裕":{"유": "0E"},+ "裘":{"구": "1N"},+ "裙":{"군": "0N"},+ "補":{"보": "0E"},+ "裝":{"장": "0E"},+ "裟":{"사": "0N"},+ "裡":{"리": "0N", "이": "0"},+ "裨":{"비": "0N"},+ "裯":{"주": "1N"},+ "裱":{"표": "1N"},+ "裳":{"상": "0E"},+ "裴":{"배": "0N"},+ "裵":{"배": "0N"},+ "裸":{"나": "0", "라": "0N"},+ "裹":{"과": "1N"},+ "製":{"제": "0E"},+ "裾":{"거": "1N"},+ "褄":{"처": "1"},+ "複":{"복": "0E"},+ "褊":{"편": "1N"},+ "褌":{"곤": "1N"},+ "褐":{"갈": "0N"},+ "褑":{"원": "N"},+ "褒":{"포": "0N"},+ "褓":{"보": "0N"},+ "褕":{"유": "1N"},+ "褘":{"위": "0N"},+ "褙":{"배": "0N"},+ "褚":{"저": "1N"},+ "褥":{"욕": "0N"},+ "褧":{"경": "1N"},+ "褪":{"퇴": "0N"},+ "褫":{"치": "1N"},+ "褯":{"석": "N", "자": "N"},+ "褰":{"건": "1N"},+ "褶":{"습": "0N"},+ "褸":{"루": "0N"},+ "褺":{"첩": "1N"},+ "褻":{"설": "0N"},+ "襁":{"강": "0N"},+ "襄":{"양": "0N"},+ "襍":{"잡": "1N"},+ "襒":{"별": "N"},+ "襖":{"오": "1N"},+ "襘":{"괴": "1N"},+ "襜":{"첨": "1N"},+ "襞":{"벽": "1N"},+ "襟":{"금": "0N"},+ "襠":{"당": "1N"},+ "襤":{"남": "0", "람": "0N"},+ "襪":{"말": "0N"},+ "襭":{"힐": "1N"},+ "襯":{"친": "1N"},+ "襲":{"습": "0E"},+ "襴":{"란": "1N"},+ "西":{"서": "0E"},+ "要":{"요": "0E"},+ "覃":{"담": "0N"},+ "覆":{"복": "0E"},+ "覇":{"패": "0N"},+ "覈":{"핵": "1N"},+ "覉":{"기": "1"},+ "見":{"견": "0E", "현": "0N"},+ "規":{"규": "0E"},+ "覓":{"멱": "0N"},+ "視":{"시": "0E"},+ "覗":{"사": "1N"},+ "覘":{"점": "1N"},+ "覠":{"균": "N"},+ "覡":{"격": "0N"},+ "覨":{"악": "1N"},+ "覩":{"도": "0N"},+ "親":{"친": "0E"},+ "覬":{"기": "1N"},+ "覯":{"구": "1N"},+ "覲":{"근": "0N"},+ "覶":{"라": "N"},+ "覷":{"처": "1N"},+ "覺":{"각": "0E"},+ "覽":{"람": "0E"},+ "覿":{"적": "1N"},+ "觀":{"관": "0E"},+ "角":{"각": "0E"},+ "觔":{"근": "1N"},+ "觖":{"결": "1N"},+ "觗":{"지": "N"},+ "觚":{"고": "1N"},+ "觜":{"자": "1N"},+ "觝":{"저": "1N"},+ "解":{"해": "0E"},+ "觥":{"굉": "1N"},+ "觰":{"다": "N"},+ "觱":{"필": "1N"},+ "觳":{"곡": "1N"},+ "觴":{"상": "0N"},+ "觸":{"촉": "0E"},+ "言":{"언": "0E"},+ "訂":{"정": "0E"},+ "訃":{"부": "0N"},+ "訇":{"굉": "1N"},+ "計":{"계": "0E"},+ "訉":{"범": "1N"},+ "訊":{"신": "0N"},+ "訌":{"홍": "0N"},+ "討":{"토": "0E"},+ "訐":{"알": "1N"},+ "訑":{"이": "1N"},+ "訓":{"훈": "0E"},+ "訔":{"은": "1N"},+ "訕":{"산": "1N"},+ "訖":{"흘": "0N"},+ "託":{"탁": "0N"},+ "記":{"기": "0E"},+ "訛":{"와": "0N"},+ "訝":{"아": "0N"},+ "訟":{"송": "0E"},+ "訢":{"은": "N", "흔": "1"},+ "訣":{"결": "0N"},+ "訥":{"눌": "0N"},+ "訪":{"방": "0E"},+ "設":{"설": "0E"},+ "許":{"허": "0E"},+ "訴":{"소": "0E"},+ "訶":{"가": "0N"},+ "診":{"진": "0N"},+ "註":{"주": "0N"},+ "証":{"정": "1N"},+ "訾":{"자": "1N"},+ "詁":{"고": "1N"},+ "詆":{"저": "1N"},+ "詋":{"주": "1N"},+ "詐":{"사": "0E"},+ "詑":{"이": "1", "타": "N"},+ "詔":{"조": "0N"},+ "評":{"평": "0E"},+ "詖":{"피": "1N"},+ "詗":{"형": "1N"},+ "詘":{"굴": "1N"},+ "詛":{"저": "0N"},+ "詞":{"사": "0E"},+ "詠":{"영": "0E"},+ "詡":{"후": "1N"},+ "詢":{"순": "0N"},+ "詣":{"예": "0N"},+ "試":{"시": "0E"},+ "詩":{"시": "0E"},+ "詫":{"타": "1N"},+ "詬":{"구": "1N"},+ "詭":{"궤": "0N"},+ "詮":{"전": "0N"},+ "詰":{"힐": "0N"},+ "話":{"화": "0E"},+ "該":{"해": "0E"},+ "詳":{"상": "0E"},+ "詵":{"선": "0N"},+ "詹":{"첨": "0N"},+ "詼":{"회": "1N"},+ "詿":{"괘": "1N"},+ "誂":{"조": "1N"},+ "誄":{"뢰": "1N"},+ "誅":{"주": "0N"},+ "誆":{"광": "1N"},+ "誇":{"과": "0E"},+ "誌":{"지": "0E"},+ "認":{"인": "0E"},+ "誑":{"광": "1N"},+ "誓":{"서": "0E"},+ "誕":{"탄": "0E"},+ "誘":{"유": "0E"},+ "誚":{"초": "1N"},+ "語":{"어": "0E"},+ "誠":{"성": "0EN"},+ "誡":{"계": "0N"},+ "誢":{"현": "1N"},+ "誣":{"무": "0N"},+ "誤":{"오": "0E"},+ "誥":{"고": "0N"},+ "誦":{"송": "0E"},+ "誧":{"포": "1N"},+ "誨":{"회": "0N"},+ "說":{"설": "0E", "세": "0N", "열": "0N"},+ "誰":{"수": "0E"},+ "課":{"과": "0E"},+ "誹":{"비": "0N"},+ "誼":{"의": "0N"},+ "誾":{"은": "0N"},+ "調":{"조": "0E", "주": "N"},+ "諂":{"첨": "0N"},+ "諄":{"순": "0N"},+ "談":{"담": "0E"},+ "諉":{"위": "1N"},+ "請":{"청": "0EN"},+ "諍":{"쟁": "0N"},+ "諏":{"추": "0N"},+ "諒":{"량": "0E", "양": "0"},+ "論":{"논": "0", "론": "0E"},+ "諛":{"유": "0N"},+ "諜":{"첩": "0N"},+ "諝":{"서": "N"},+ "諞":{"편": "1N"},+ "諟":{"시": "1N", "체": "N"},+ "諠":{"훤": "1N"},+ "諡":{"시": "0N"},+ "諤":{"악": "1N"},+ "諦":{"체": "0N"},+ "諧":{"해": "0N"},+ "諪":{"정": "0N"},+ "諫":{"간": "0N"},+ "諭":{"유": "0N"},+ "諮":{"자": "0N"},+ "諰":{"시": "1N"},+ "諱":{"휘": "0N"},+ "諲":{"인": "N"},+ "諳":{"암": "1N"},+ "諴":{"함": "1N"},+ "諶":{"심": "0N"},+ "諷":{"풍": "0N"},+ "諸":{"제": "0E"},+ "諺":{"언": "0N"},+ "諼":{"훤": "1N"},+ "諾":{"낙": "0E", "락": "0"},+ "謀":{"모": "0E"},+ "謁":{"알": "0E"},+ "謂":{"위": "0E"},+ "謄":{"등": "0N"},+ "謇":{"건": "1N"},+ "謌":{"가": "1N"},+ "謎":{"미": "0N"},+ "謐":{"밀": "0N"},+ "謑":{"혜": "1N"},+ "謔":{"학": "0N"},+ "謖":{"속": "0N"},+ "謗":{"방": "0N"},+ "謙":{"겸": "0E"},+ "謚":{"익": "0N"},+ "講":{"강": "0E"},+ "謜":{"원": "1N"},+ "謝":{"사": "0E"},+ "謠":{"요": "0E"},+ "謣":{"우": "1N"},+ "謦":{"경": "1N"},+ "謨":{"모": "0N"},+ "謫":{"적": "0N"},+ "謬":{"류": "0N"},+ "謳":{"구": "0N"},+ "謷":{"오": "1N"},+ "謹":{"근": "0E"},+ "謼":{"효": "N"},+ "謾":{"만": "1N"},+ "譁":{"화": "0N"},+ "譃":{"후": "1N"},+ "譆":{"희": "N"},+ "證":{"증": "0E"},+ "譌":{"와": "1N"},+ "譎":{"휼": "0N"},+ "譏":{"기": "0N"},+ "譓":{"혜": "N"},+ "譔":{"선": "1N"},+ "譖":{"참": "1N"},+ "識":{"식": "0E", "지": "0N"},+ "譙":{"초": "1N"},+ "譚":{"담": "0N"},+ "譜":{"보": "0E"},+ "譞":{"현": "N"},+ "譟":{"조": "1N"},+ "警":{"경": "0E"},+ "譫":{"섬": "1N"},+ "譬":{"비": "0N"},+ "譯":{"역": "0E"},+ "議":{"의": "0E"},+ "譱":{"선": "1N"},+ "譴":{"견": "0N"},+ "護":{"호": "0E"},+ "譽":{"예": "0E"},+ "譿":{"혜": "1N"},+ "讀":{"독": "0E", "두": "0N"},+ "讃":{"찬": "N"},+ "讉":{"유": "1N"},+ "變":{"변": "0E"},+ "讌":{"연": "1N"},+ "讎":{"수": "1N"},+ "讐":{"수": "0N"},+ "讒":{"참": "0N"},+ "讓":{"양": "0E"},+ "讖":{"참": "0N"},+ "讚":{"찬": "0E"},+ "讜":{"당": "1N"},+ "讞":{"언": "1N"},+ "谷":{"곡": "0E"},+ "谿":{"계": "0N"},+ "豁":{"활": "0N"},+ "豆":{"두": "0E"},+ "豇":{"강": "1N"},+ "豈":{"개": "0N", "기": "0E"},+ "豉":{"시": "1N"},+ "豊":{"풍": "0N"},+ "豌":{"완": "0N"},+ "豎":{"수": "1N"},+ "豐":{"풍": "E"},+ "豕":{"시": "0N"},+ "豖":{"축": "1N"},+ "豚":{"돈": "0E"},+ "象":{"상": "0E"},+ "豢":{"환": "1N"},+ "豨":{"희": "1N"},+ "豪":{"호": "0E"},+ "豫":{"예": "0E"},+ "豬":{"저": "1"},+ "豳":{"반": "N", "빈": "1N"},+ "豸":{"치": "1N"},+ "豹":{"표": "0N"},+ "豺":{"시": "0N"},+ "貂":{"초": "0N"},+ "貃":{"맥": "1N"},+ "貊":{"맥": "0N"},+ "貌":{"모": "0E"},+ "貍":{"리": "1N"},+ "貓":{"묘": "1N"},+ "貔":{"비": "1N"},+ "貘":{"맥": "1N"},+ "貝":{"배": "N", "패": "0E"},+ "貞":{"정": "0E"},+ "貟":{"원": "N"},+ "負":{"부": "0E"},+ "財":{"재": "0E"},+ "貢":{"공": "0E"},+ "貧":{"빈": "0E"},+ "貨":{"화": "0E"},+ "販":{"판": "0E"},+ "貪":{"탐": "0E"},+ "貫":{"관": "0E"},+ "責":{"채": "N", "책": "0E"},+ "貯":{"저": "0E"},+ "貰":{"세": "0N"},+ "貲":{"자": "1N"},+ "貳":{"이": "0N"},+ "貴":{"귀": "0E"},+ "貶":{"폄": "0N"},+ "買":{"매": "0E"},+ "貸":{"대": "0E"},+ "貹":{"성": "N"},+ "貺":{"황": "1N"},+ "費":{"비": "0E"},+ "貼":{"첩": "0N"},+ "貽":{"이": "0N"},+ "貿":{"무": "0E"},+ "賀":{"하": "0E"},+ "賁":{"분": "0N"},+ "賂":{"뇌": "0", "뢰": "0N"},+ "賃":{"임": "0E"},+ "賄":{"회": "0N"},+ "賆":{"변": "1N"},+ "資":{"자": "0E"},+ "賈":{"가": "0N", "고": "0N"},+ "賊":{"적": "0E"},+ "賑":{"진": "0N"},+ "賓":{"빈": "0E"},+ "賙":{"주": "1N"},+ "賚":{"뢰": "0N"},+ "賛":{"찬": "N"},+ "賜":{"사": "0E"},+ "賞":{"상": "0E"},+ "賠":{"배": "0N"},+ "賡":{"갱": "1N"},+ "賢":{"현": "0E"},+ "賣":{"매": "0E"},+ "賤":{"천": "0E"},+ "賥":{"수": "N"},+ "賦":{"부": "0E"},+ "質":{"질": "0E"},+ "賬":{"장": "1"},+ "賭":{"도": "0N"},+ "賰":{"춘": "N"},+ "賱":{"운": "N"},+ "賳":{"재": "N"},+ "賴":{"뢰": "0E"},+ "賻":{"부": "0N"},+ "購":{"구": "0N"},+ "賽":{"새": "0N"},+ "贄":{"지": "0N"},+ "贅":{"췌": "0N"},+ "贇":{"빈": "N", "윤": "0N"},+ "贈":{"증": "0E"},+ "贊":{"찬": "0E"},+ "贋":{"안": "1"},+ "贍":{"섬": "0N"},+ "贏":{"영": "1N"},+ "贐":{"신": "1N"},+ "贓":{"장": "0N"},+ "贔":{"비": "1N"},+ "贖":{"속": "0N"},+ "贛":{"공": "1N"},+ "赤":{"적": "0E"},+ "赦":{"사": "0N"},+ "赧":{"난": "1N"},+ "赫":{"혁": "0N"},+ "赭":{"자": "1N"},+ "赮":{"하": "N"},+ "走":{"주": "0E"},+ "赳":{"규": "0N"},+ "赴":{"부": "0E"},+ "赶":{"간": "1N"},+ "起":{"기": "0E"},+ "趁":{"진": "1N"},+ "超":{"초": "0E"},+ "越":{"월": "0E"},+ "趎":{"주": "1N"},+ "趐":{"혈": "1N"},+ "趙":{"조": "0N"},+ "趠":{"초": "1N"},+ "趣":{"취": "0E"},+ "趨":{"추": "0N"},+ "趫":{"교": "1N"},+ "趲":{"찬": "1N"},+ "足":{"족": "0E"},+ "趺":{"부": "0N"},+ "趾":{"지": "0N"},+ "跂":{"기": "1N"},+ "跆":{"태": "0N"},+ "跋":{"발": "0N"},+ "跌":{"질": "0N"},+ "跎":{"타": "1N"},+ "跏":{"가": "0N"},+ "跕":{"접": "1N"},+ "跖":{"척": "1N"},+ "跗":{"부": "1N"},+ "跛":{"파": "0N"},+ "距":{"거": "0E"},+ "跟":{"근": "1N"},+ "跡":{"적": "0E"},+ "跣":{"선": "0N"},+ "跨":{"과": "0N"},+ "跪":{"궤": "1N"},+ "跫":{"공": "1N"},+ "跬":{"규": "1N"},+ "跭":{"강": "N"},+ "路":{"노": "0", "로": "0E"},+ "跱":{"치": "1N"},+ "跳":{"도": "0E"},+ "跼":{"국": "1N"},+ "踆":{"준": "1N"},+ "踈":{"소": "1"},+ "踉":{"량": "1N"},+ "踊":{"용": "0N"},+ "踏":{"답": "0E"},+ "踐":{"천": "0E"},+ "踔":{"탁": "1N"},+ "踝":{"과": "1N"},+ "踞":{"거": "0N"},+ "踟":{"지": "1N"},+ "踪":{"종": "0N"},+ "踰":{"유": "0N"},+ "踴":{"용": "1N"},+ "踵":{"종": "0N"},+ "踶":{"제": "1N"},+ "踺":{"건": "N"},+ "踽":{"우": "1N"},+ "蹀":{"접": "1N"},+ "蹂":{"유": "0N"},+ "蹄":{"제": "0N"},+ "蹇":{"건": "0N"},+ "蹈":{"도": "0N"},+ "蹉":{"차": "0N"},+ "蹊":{"혜": "0N"},+ "蹌":{"창": "1N"},+ "蹏":{"제": "1N"},+ "蹕":{"필": "1N"},+ "蹙":{"축": "0N"},+ "蹜":{"축": "1N"},+ "蹟":{"적": "0N"},+ "蹠":{"척": "0N"},+ "蹣":{"만": "1N"},+ "蹤":{"종": "1N"},+ "蹲":{"준": "1N"},+ "蹴":{"축": "0N"},+ "蹶":{"궐": "0N"},+ "蹻":{"교": "1N"},+ "躁":{"조": "0N"},+ "躅":{"촉": "1N"},+ "躇":{"저": "0N"},+ "躉":{"돈": "1N"},+ "躊":{"주": "0N"},+ "躋":{"제": "1N"},+ "躍":{"약": "0E"},+ "躐":{"렵": "1N"},+ "躑":{"척": "1N"},+ "躓":{"지": "1N"},+ "躔":{"전": "1N"},+ "躙":{"린": "1N"},+ "躞":{"섭": "N"},+ "躡":{"섭": "1N"},+ "躩":{"곽": "1"},+ "躪":{"린": "0N"},+ "身":{"신": "0E"},+ "躬":{"궁": "0N"},+ "躱":{"타": "1N"},+ "躳":{"궁": "1N"},+ "躾":{"미": "N"},+ "軀":{"구": "0N"},+ "軆":{"체": "1"},+ "車":{"거": "0E", "차": "0N"},+ "軋":{"알": "0N"},+ "軌":{"궤": "0E"},+ "軍":{"군": "0E"},+ "軒":{"헌": "0E"},+ "軞":{"모": "N"},+ "軟":{"연": "0E"},+ "軨":{"령": "1N"},+ "軫":{"진": "0N"},+ "軸":{"축": "0N"},+ "軹":{"지": "1N"},+ "軺":{"초": "1N"},+ "軻":{"가": "0N"},+ "軼":{"일": "1N"},+ "軾":{"식": "0N"},+ "較":{"교": "0E"},+ "輅":{"로": "0N"},+ "輇":{"전": "1N"},+ "輈":{"주": "1N"},+ "載":{"재": "0E"},+ "輒":{"첩": "0N"},+ "輓":{"만": "0N"},+ "輔":{"보": "0N"},+ "輕":{"경": "0E"},+ "輛":{"량": "0N"},+ "輜":{"치": "0N"},+ "輝":{"휘": "0E"},+ "輞":{"망": "0N"},+ "輟":{"철": "0N"},+ "輦":{"련": "0N", "연": "0"},+ "輧":{"병": "0N"},+ "輨":{"관": "1N"},+ "輩":{"배": "0E"},+ "輪":{"륜": "0E", "윤": "0"},+ "輭":{"연": "N"},+ "輯":{"집": "0N"},+ "輰":{"양": "1N"},+ "輳":{"주": "0N"},+ "輸":{"수": "0E"},+ "輹":{"복": "0N"},+ "輻":{"복": "0N", "폭": "0N"},+ "輾":{"전": "0N"},+ "輿":{"여": "0E"},+ "轀":{"온": "1N"},+ "轂":{"곡": "1N"},+ "轄":{"할": "0N"},+ "轅":{"원": "0N"},+ "轆":{"록": "1N"},+ "轉":{"전": "0E"},+ "轍":{"철": "0N"},+ "轎":{"교": "0N"},+ "轒":{"분": "1N"},+ "轔":{"린": "1N"},+ "轗":{"감": "1N"},+ "轘":{"환": "1N"},+ "轝":{"여": "0N"},+ "轞":{"함": "1N"},+ "轟":{"굉": "0N"},+ "轡":{"비": "1N"},+ "轢":{"력": "0N", "역": "0"},+ "轣":{"력": "1N"},+ "轤":{"로": "1N"},+ "辛":{"신": "0E"},+ "辜":{"고": "0N"},+ "辟":{"벽": "N", "피": "1"},+ "辢":{"랄": "1N"},+ "辣":{"랄": "0N"},+ "辦":{"판": "0N"},+ "辨":{"변": "0E"},+ "辭":{"사": "0E"},+ "辮":{"변": "1N"},+ "辯":{"변": "0E"},+ "辰":{"신": "0N", "진": "0E"},+ "辱":{"욕": "0E"},+ "農":{"농": "0E"},+ "辻":{"십": "1"},+ "辿":{"천": "1N"},+ "迀":{"간": "1N"},+ "迂":{"우": "0N"},+ "迃":{"오": "1N"},+ "迄":{"흘": "1N"},+ "迅":{"신": "0N"},+ "迍":{"둔": "1N"},+ "迎":{"영": "0E"},+ "近":{"근": "0E"},+ "迓":{"아": "1N"},+ "返":{"반": "0E"},+ "迕":{"오": "1N"},+ "迢":{"초": "1N"},+ "迤":{"이": "1N"},+ "迥":{"형": "1N"},+ "迦":{"가": "0N"},+ "迨":{"태": "1N"},+ "迪":{"적": "0N"},+ "迫":{"박": "0E"},+ "迬":{"왕": "1N"},+ "迭":{"질": "0N"},+ "述":{"술": "0E"},+ "迲":{"겁": "0N"},+ "迴":{"회": "1N"},+ "迷":{"미": "0E"},+ "迸":{"병": "1N"},+ "迹":{"적": "0N"},+ "迺":{"내": "1N"},+ "迼":{"결": "N"},+ "追":{"추": "0E"},+ "迿":{"준": "N"},+ "退":{"퇴": "0E"},+ "送":{"송": "0E"},+ "适":{"괄": "0N"},+ "逃":{"도": "0E"},+ "逅":{"후": "0N"},+ "逆":{"역": "0E"},+ "逈":{"형": "0N"},+ "逋":{"포": "0N"},+ "逌":{"유": "1N"},+ "逍":{"소": "0N"},+ "逎":{"주": "N"},+ "透":{"투": "0E"},+ "逐":{"축": "0E"},+ "逑":{"구": "0N"},+ "途":{"도": "0E"},+ "逕":{"경": "0N"},+ "逖":{"적": "1N"},+ "逗":{"두": "0N"},+ "這":{"저": "0N"},+ "通":{"통": "0E"},+ "逝":{"서": "0E"},+ "逞":{"령": "0N"},+ "速":{"속": "0E"},+ "造":{"조": "0E"},+ "逡":{"준": "0N"},+ "逢":{"봉": "0E"},+ "連":{"련": "0E", "연": "0"},+ "逮":{"체": "0E"},+ "週":{"주": "0N"},+ "進":{"진": "0E"},+ "逴":{"탁": "1N"},+ "逵":{"규": "0N"},+ "逶":{"위": "1N"},+ "逸":{"일": "0E"},+ "逼":{"핍": "0N"},+ "逾":{"유": "0N"},+ "遁":{"둔": "0N"},+ "遂":{"수": "0E"},+ "遇":{"우": "0E"},+ "遉":{"정": "1N"},+ "遊":{"유": "0E"},+ "運":{"운": "0E"},+ "遍":{"편": "0E"},+ "過":{"과": "0E"},+ "遏":{"알": "1N"},+ "遐":{"하": "0N"},+ "遑":{"황": "0N"},+ "遒":{"주": "1N"},+ "道":{"도": "0E"},+ "達":{"달": "0E"},+ "違":{"위": "0E"},+ "遘":{"구": "1N"},+ "遙":{"요": "0E"},+ "遛":{"류": "1N"},+ "遜":{"손": "0N"},+ "遝":{"답": "0N"},+ "遞":{"체": "0E"},+ "遠":{"원": "0E"},+ "遡":{"소": "0N"},+ "遣":{"견": "0E"},+ "遨":{"오": "1N"},+ "適":{"적": "0E"},+ "遬":{"속": "1N"},+ "遭":{"조": "0N"},+ "遮":{"차": "0N"},+ "遯":{"둔": "0N"},+ "遲":{"지": "0E"},+ "遵":{"준": "0E"},+ "遶":{"요": "1N"},+ "遷":{"천": "0E"},+ "選":{"선": "0E"},+ "遺":{"유": "0E"},+ "遼":{"료": "0N", "요": "0"},+ "遽":{"거": "0N"},+ "遾":{"서": "N"},+ "避":{"피": "0E"},+ "邀":{"요": "0N"},+ "邁":{"매": "0N"},+ "邂":{"해": "0N"},+ "邃":{"수": "0N"},+ "還":{"환": "0E"},+ "邅":{"전": "1N"},+ "邇":{"이": "0N"},+ "邈":{"막": "0N"},+ "邊":{"변": "0E"},+ "邌":{"려": "1N"},+ "邍":{"원": "N"},+ "邏":{"나": "0", "라": "0N"},+ "邐":{"리": "1N"},+ "邑":{"읍": "0E"},+ "邕":{"옹": "0N"},+ "邗":{"한": "N"},+ "邘":{"우": "N"},+ "邙":{"망": "0N"},+ "邠":{"빈": "1N"},+ "邢":{"형": "0N"},+ "那":{"나": "0E"},+ "邦":{"방": "0E"},+ "邨":{"촌": "0N"},+ "邪":{"사": "0E"},+ "邯":{"감": "0N"},+ "邰":{"태": "0N"},+ "邱":{"구": "0N"},+ "邳":{"비": "1N"},+ "邵":{"소": "0N"},+ "邸":{"저": "0N"},+ "邽":{"규": "1N"},+ "邾":{"주": "N"},+ "郁":{"욱": "0N"},+ "郃":{"합": "1N"},+ "郄":{"극": "1N"},+ "郅":{"질": "1N"},+ "郊":{"교": "0E"},+ "郎":{"랑": "N"},+ "郜":{"고": "1N"},+ "郝":{"학": "1N"},+ "郞":{"낭": "0", "랑": "0E"},+ "郡":{"군": "0E"},+ "郢":{"영": "1N"},+ "部":{"부": "0E"},+ "郪":{"처": "1N"},+ "郫":{"비": "1N"},+ "郭":{"곽": "0E"},+ "郯":{"담": "1N"},+ "郳":{"예": "N"},+ "郴":{"침": "1N"},+ "郵":{"우": "0E"},+ "都":{"도": "0E"},+ "鄂":{"악": "0N"},+ "鄒":{"추": "0N"},+ "鄕":{"향": "0E"},+ "鄖":{"운": "N"},+ "鄗":{"교": "N", "호": "N"},+ "鄙":{"비": "0N"},+ "鄞":{"은": "1N"},+ "鄢":{"언": "1N"},+ "鄣":{"장": "1N"},+ "鄧":{"등": "0N"},+ "鄭":{"정": "0N"},+ "鄰":{"린": "1E"},+ "鄱":{"파": "1N"},+ "鄲":{"단": "0N"},+ "鄴":{"업": "1N"},+ "鄽":{"전": "1N"},+ "酈":{"력": "1N"},+ "酉":{"유": "0E"},+ "酊":{"정": "0N"},+ "酋":{"추": "0N"},+ "酌":{"작": "0E"},+ "配":{"배": "0E"},+ "酎":{"주": "0N"},+ "酒":{"주": "0E"},+ "酖":{"탐": "1N"},+ "酗":{"후": "1N"},+ "酢":{"초": "0N"},+ "酣":{"감": "1N"},+ "酤":{"고": "1N"},+ "酥":{"소": "1N"},+ "酩":{"명": "0N"},+ "酪":{"낙": "0", "락": "0N"},+ "酬":{"수": "0N"},+ "酲":{"정": "1N"},+ "酴":{"도": "1N"},+ "酵":{"효": "0N"},+ "酶":{"매": "1N"},+ "酷":{"혹": "0N"},+ "酸":{"산": "0N"},+ "酹":{"뢰": "1N"},+ "醃":{"엄": "1N"},+ "醇":{"순": "0N"},+ "醉":{"취": "0E"},+ "醋":{"초": "0N"},+ "醍":{"제": "0N"},+ "醐":{"호": "1N"},+ "醒":{"성": "0N"},+ "醜":{"추": "0E"},+ "醞":{"온": "1N"},+ "醢":{"해": "1N"},+ "醪":{"료": "1N"},+ "醫":{"의": "0E"},+ "醬":{"장": "0N"},+ "醮":{"초": "0N"},+ "醯":{"혜": "0N"},+ "醱":{"발": "0N"},+ "醲":{"농": "1N"},+ "醴":{"례": "0N", "예": "0"},+ "醵":{"갹": "0N"},+ "醼":{"연": "N"},+ "釀":{"양": "0N"},+ "釁":{"흔": "1N"},+ "釃":{"시": "1N"},+ "釅":{"염": "1"},+ "釆":{"변": "N"},+ "采":{"채": "0N"},+ "釉":{"유": "0N"},+ "釋":{"석": "0E"},+ "里":{"리": "0E", "이": "0"},+ "重":{"중": "0E"},+ "野":{"야": "0E"},+ "量":{"량": "0E", "양": "0"},+ "釐":{"리": "0N"},+ "金":{"금": "0E", "김": "0N"},+ "釗":{"쇠": "0N"},+ "釘":{"정": "0N"},+ "釜":{"부": "0N"},+ "針":{"침": "0E"},+ "釣":{"조": "0N"},+ "釤":{"삼": "1N"},+ "釥":{"초": "N"},+ "釦":{"구": "1N"},+ "釧":{"천": "0N"},+ "釩":{"범": "N"},+ "釪":{"우": "0N"},+ "釭":{"공": "1N"},+ "釵":{"채": "0N"},+ "釿":{"근": "1N"},+ "鈇":{"부": "1N"},+ "鈍":{"둔": "0E"},+ "鈐":{"검": "0N"},+ "鈑":{"판": "0N"},+ "鈒":{"삽": "0N"},+ "鈔":{"초": "1N"},+ "鈕":{"뉴": "N"},+ "鈗":{"윤": "0N"},+ "鈜":{"횡": "1N"},+ "鈞":{"균": "0N"},+ "鈟":{"조": "1N"},+ "鈦":{"태": "N"},+ "鈱":{"민": "N"},+ "鈴":{"령": "0N", "영": "0"},+ "鈵":{"병": "1N"},+ "鈷":{"고": "1N"},+ "鈸":{"발": "1N"},+ "鈺":{"옥": "0N"},+ "鈿":{"전": "0N"},+ "鉀":{"갑": "0N"},+ "鉁":{"진": "1N"},+ "鉄":{"철": "N"},+ "鉅":{"거": "0N"},+ "鉉":{"현": "0N"},+ "鉋":{"포": "1N"},+ "鉍":{"필": "N"},+ "鉎":{"생": "1N"},+ "鉏":{"서": "1N"},+ "鉐":{"석": "1N"},+ "鉑":{"박": "N"},+ "鉒":{"주": "1N"},+ "鉗":{"겸": "0N"},+ "鉛":{"연": "0E"},+ "鉞":{"월": "0N"},+ "鉢":{"발": "0N"},+ "鉤":{"구": "0N"},+ "鉥":{"술": "0N"},+ "鉦":{"정": "0N"},+ "鉷":{"홍": "1N"},+ "鉸":{"교": "1N"},+ "鉼":{"병": "1N"},+ "鉾":{"모": "1"},+ "銀":{"은": "0E"},+ "銃":{"총": "0E"},+ "銅":{"동": "0E"},+ "銋":{"임": "1N"},+ "銑":{"선": "0N"},+ "銓":{"전": "0N"},+ "銕":{"철": "1N"},+ "銖":{"수": "0N"},+ "銘":{"명": "0E"},+ "銙":{"과": "1N"},+ "銚":{"조": "1N"},+ "銛":{"섬": "1N"},+ "銜":{"함": "0N"},+ "銳":{"예": "0E"},+ "銴":{"세": "N"},+ "銶":{"구": "0N"},+ "銷":{"소": "0N"},+ "銹":{"수": "0N"},+ "鋆":{"윤": "1N"},+ "鋌":{"정": "0N"},+ "鋏":{"협": "0N"},+ "鋑":{"전": "1N"},+ "鋒":{"봉": "0N"},+ "鋕":{"지": "N"},+ "鋗":{"현": "1N"},+ "鋟":{"침": "1N"},+ "鋤":{"서": "0N"},+ "鋥":{"정": "1N"},+ "鋪":{"포": "0N"},+ "鋲":{"병": "1"},+ "鋸":{"거": "0N"},+ "鋹":{"창": "1N"},+ "鋺":{"완": "N", "원": "1N"},+ "鋼":{"강": "0E"},+ "鋽":{"조": "1N"},+ "鋾":{"도": "N"},+ "錀":{"륜": "N"},+ "錄":{"녹": "0", "록": "0E"},+ "錆":{"창": "1"},+ "錏":{"아": "1N"},+ "錐":{"추": "0N"},+ "錕":{"곤": "1N"},+ "錘":{"추": "0N"},+ "錙":{"치": "1N"},+ "錚":{"쟁": "0N"},+ "錞":{"순": "0N"},+ "錟":{"담": "0N"},+ "錠":{"정": "0N"},+ "錡":{"기": "0N"},+ "錢":{"전": "0E"},+ "錣":{"철": "1N"},+ "錤":{"기": "0N"},+ "錦":{"금": "0E"},+ "錧":{"관": "1N"},+ "錨":{"묘": "0N"},+ "錪":{"전": "1N"},+ "錫":{"석": "0N"},+ "錬":{"동": "1"},+ "錮":{"고": "0N"},+ "錯":{"착": "0E"},+ "鍈":{"영": "0N"},+ "鍉":{"시": "1N"},+ "鍊":{"련": "0E", "연": "0"},+ "鍋":{"과": "0N"},+ "鍍":{"도": "0N"},+ "鍑":{"복": "N"},+ "鍔":{"악": "0N"},+ "鍗":{"제": "1N"},+ "鍛":{"단": "0N"},+ "鍜":{"하": "1N"},+ "鍝":{"우": "1N"},+ "鍤":{"삽": "1N"},+ "鍥":{"결": "N"},+ "鍫":{"초": "1N"},+ "鍬":{"초": "1N"},+ "鍮":{"유": "0N"},+ "鍰":{"환": "1N"},+ "鍵":{"건": "0N"},+ "鍼":{"침": "0N"},+ "鍾":{"종": "0N"},+ "鎊":{"방": "1N"},+ "鎌":{"겸": "0N"},+ "鎔":{"용": "0N"},+ "鎖":{"쇄": "0E"},+ "鎗":{"쟁": "1N"},+ "鎚":{"추": "0N"},+ "鎛":{"박": "1N"},+ "鎟":{"상": "1N"},+ "鎠":{"강": "N"},+ "鎡":{"자": "1N"},+ "鎣":{"형": "0N"},+ "鎤":{"황": "1N"},+ "鎧":{"개": "0N"},+ "鎬":{"호": "0N"},+ "鎭":{"진": "0E"},+ "鎰":{"일": "0N"},+ "鎻":{"쇄": "N"},+ "鏃":{"족": "0N"},+ "鏇":{"선": "1N"},+ "鏈":{"련": "1N"},+ "鏊":{"오": "1N"},+ "鏋":{"만": "1N"},+ "鏌":{"막": "1N"},+ "鏑":{"적": "0N"},+ "鏖":{"오": "1N"},+ "鏗":{"갱": "1N"},+ "鏘":{"장": "1N"},+ "鏜":{"당": "1N"},+ "鏝":{"만": "1N"},+ "鏞":{"용": "0N"},+ "鏟":{"산": "1N"},+ "鏡":{"경": "0E"},+ "鏢":{"표": "1N"},+ "鏤":{"루": "0N"},+ "鏦":{"총": "1N"},+ "鏨":{"참": "1N"},+ "鏶":{"집": "0N"},+ "鏸":{"혜": "N"},+ "鏹":{"강": "N"},+ "鏻":{"린": "1N"},+ "鐃":{"뇨": "1N"},+ "鐄":{"횡": "0N"},+ "鐏":{"준": "1N"},+ "鐐":{"료": "1N"},+ "鐓":{"대": "1N"},+ "鐔":{"심": "1N"},+ "鐘":{"종": "0E"},+ "鐙":{"등": "1N"},+ "鐥":{"선": "0N"},+ "鐪":{"로": "1N"},+ "鐫":{"전": "0N"},+ "鐵":{"철": "0E"},+ "鐶":{"환": "1N"},+ "鐸":{"탁": "0N"},+ "鐺":{"당": "1N"},+ "鑂":{"훈": "1N"},+ "鑄":{"주": "0E"},+ "鑊":{"확": "1N"},+ "鑌":{"빈": "1N"},+ "鑑":{"감": "0E"},+ "鑒":{"감": "0N"},+ "鑕":{"질": "1N"},+ "鑛":{"광": "0E"},+ "鑞":{"랍": "1N"},+ "鑠":{"삭": "1N"},+ "鑢":{"려": "1N"},+ "鑣":{"표": "1N"},+ "鑪":{"로": "1N"},+ "鑫":{"흠": "N"},+ "鑰":{"약": "1N"},+ "鑱":{"참": "1N"},+ "鑲":{"양": "1N"},+ "鑵":{"관": "1N"},+ "鑷":{"섭": "1N"},+ "鑼":{"라": "1N"},+ "鑽":{"찬": "0N"},+ "鑾":{"란": "1N"},+ "鑿":{"착": "0N"},+ "長":{"장": "0E"},+ "門":{"문": "0E"},+ "閃":{"섬": "0N"},+ "閈":{"한": "1N"},+ "閉":{"폐": "0E"},+ "閊":{"산": "1"},+ "開":{"개": "0E"},+ "閎":{"굉": "1N"},+ "閏":{"윤": "0E"},+ "閑":{"한": "0E"},+ "閒":{"한": "0N"},+ "間":{"간": "0E"},+ "閔":{"민": "0N"},+ "閘":{"갑": "0N"},+ "閜":{"하": "N"},+ "閟":{"비": "1N"},+ "閠":{"윤": "N"},+ "閣":{"각": "0E"},+ "閤":{"합": "0N"},+ "閥":{"벌": "0N"},+ "閨":{"규": "0N"},+ "閩":{"민": "1N"},+ "閫":{"곤": "1N"},+ "閬":{"랑": "1N"},+ "閭":{"려": "0N", "여": "0"},+ "閱":{"열": "0E"},+ "閶":{"창": "1N"},+ "閹":{"엄": "1N"},+ "閻":{"염": "0N"},+ "閼":{"알": "0N"},+ "閽":{"혼": "1N"},+ "閾":{"역": "1N"},+ "闃":{"격": "1N"},+ "闇":{"암": "0N"},+ "闈":{"위": "1N"},+ "闊":{"활": "0N"},+ "闋":{"결": "1N"},+ "闌":{"란": "1N"},+ "闍":{"도": "1N"},+ "闓":{"개": "1N"},+ "闔":{"합": "0N"},+ "闕":{"궐": "0N"},+ "闖":{"틈": "0N"},+ "闚":{"규": "1N"},+ "關":{"관": "0E"},+ "闞":{"함": "1N"},+ "闠":{"궤": "1N"},+ "闡":{"천": "0N"},+ "闢":{"벽": "0N"},+ "闥":{"달": "1N"},+ "阜":{"부": "0N"},+ "阡":{"천": "0N"},+ "阤":{"치": "1N"},+ "阧":{"두": "N"},+ "阨":{"액": "1N"},+ "阩":{"승": "N"},+ "阪":{"판": "0N"},+ "阭":{"윤": "N"},+ "阮":{"완": "0N", "원": "0N"},+ "阯":{"지": "1N"},+ "防":{"방": "0E"},+ "阻":{"조": "0N"},+ "阿":{"아": "0N"},+ "陀":{"타": "0N"},+ "陂":{"피": "0N"},+ "附":{"부": "0E"},+ "陋":{"누": "0", "루": "0N"},+ "陌":{"맥": "0N"},+ "降":{"강": "0E", "항": "0N"},+ "限":{"한": "0E"},+ "陖":{"준": "N"},+ "陘":{"형": "1N"},+ "陛":{"폐": "0N"},+ "陜":{"합": "0N"},+ "陝":{"섬": "0N"},+ "陞":{"승": "0N"},+ "陟":{"척": "0N"},+ "陡":{"두": "1N"},+ "院":{"원": "0E"},+ "陣":{"진": "0E"},+ "除":{"제": "0E"},+ "陪":{"배": "0N"},+ "陬":{"추": "1N"},+ "陰":{"음": "0E"},+ "陲":{"수": "1N"},+ "陳":{"진": "0E"},+ "陴":{"비": "1N"},+ "陵":{"능": "0", "릉": "0E"},+ "陶":{"도": "0E"},+ "陷":{"함": "0E"},+ "陸":{"륙": "0E", "육": "0"},+ "陹":{"승": "N"},+ "陼":{"저": "1N"},+ "陽":{"양": "0E"},+ "隄":{"제": "1N"},+ "隅":{"우": "0N"},+ "隆":{"륭": "0E", "융": "0"},+ "隊":{"대": "0E"},+ "隋":{"수": "0N"},+ "隍":{"황": "0N"},+ "階":{"계": "0E"},+ "隑":{"기": "1N"},+ "隔":{"격": "0E"},+ "隕":{"운": "0N"},+ "隗":{"외": "1N"},+ "隘":{"애": "0N"},+ "隙":{"극": "0N"},+ "際":{"제": "0E"},+ "障":{"장": "0E"},+ "隣":{"린": "0N", "인": "0"},+ "隤":{"퇴": "1N"},+ "隧":{"수": "0N"},+ "隨":{"수": "0E"},+ "隩":{"오": "1N"},+ "險":{"험": "0E"},+ "隰":{"습": "1N"},+ "隱":{"은": "0E"},+ "隳":{"휴": "1N"},+ "隴":{"롱": "1N"},+ "隶":{"이": "1N"},+ "隷":{"례": "0E", "예": "0"},+ "隸":{"례": "1N"},+ "隹":{"추": "1N"},+ "隻":{"척": "0N"},+ "隼":{"준": "1N"},+ "雀":{"작": "0N"},+ "雁":{"안": "0E"},+ "雄":{"웅": "0E"},+ "雅":{"아": "0E"},+ "集":{"집": "0E"},+ "雇":{"고": "0N"},+ "雉":{"치": "0N"},+ "雋":{"전": "N", "준": "0N"},+ "雌":{"자": "0N"},+ "雍":{"옹": "0N"},+ "雎":{"저": "0N"},+ "雕":{"조": "0N"},+ "雖":{"수": "0E"},+ "雙":{"쌍": "0E"},+ "雚":{"관": "1N"},+ "雛":{"추": "0N"},+ "雜":{"잡": "0E"},+ "雝":{"옹": "1N"},+ "雞":{"계": "1N"},+ "離":{"리": "0E", "이": "0"},+ "難":{"난": "0E"},+ "雨":{"우": "0E"},+ "雩":{"우": "0N"},+ "雪":{"설": "0E"},+ "雯":{"문": "0N"},+ "雰":{"분": "0N"},+ "雲":{"운": "0E"},+ "零":{"령": "0E", "영": "0"},+ "雷":{"뇌": "0", "뢰": "0E"},+ "雹":{"박": "0N"},+ "雺":{"몽": "1N"},+ "電":{"전": "0E"},+ "需":{"수": "0E", "유": "N"},+ "霄":{"소": "1N"},+ "霅":{"삽": "1N"},+ "霆":{"정": "0N"},+ "震":{"진": "0E"},+ "霈":{"패": "1N"},+ "霉":{"매": "1N"},+ "霌":{"주": "1N"},+ "霍":{"곽": "1N"},+ "霎":{"삽": "1N"},+ "霏":{"비": "1N"},+ "霑":{"점": "0N"},+ "霓":{"예": "0N"},+ "霔":{"주": "1N"},+ "霖":{"림": "0N"},+ "霙":{"영": "0N"},+ "霜":{"상": "0E"},+ "霞":{"하": "0N"},+ "霣":{"운": "1N"},+ "霦":{"빈": "1N"},+ "霧":{"무": "0E"},+ "霪":{"음": "1N"},+ "霰":{"산": "0N"},+ "露":{"노": "0", "로": "0E"},+ "霸":{"패": "1N"},+ "霹":{"벽": "0N"},+ "霽":{"제": "0N"},+ "靂":{"력": "0N"},+ "靄":{"애": "0N"},+ "靆":{"체": "1N"},+ "靈":{"령": "0E", "영": "0"},+ "靉":{"애": "1N"},+ "靌":{"보": "1N"},+ "靑":{"청": "0E"},+ "青":{"청": "N"},+ "靕":{"진": "N"},+ "靖":{"정": "0N"},+ "靘":{"정": "N"},+ "静":{"정": "N"},+ "靚":{"정": "1N"},+ "靛":{"전": "1N"},+ "靜":{"정": "0E"},+ "靝":{"천": "1N"},+ "非":{"비": "0E"},+ "靠":{"고": "1N"},+ "靡":{"미": "0N"},+ "面":{"면": "0E"},+ "靦":{"전": "1N"},+ "靨":{"엽": "1N"},+ "革":{"혁": "0E"},+ "靭":{"인": "0N"},+ "靳":{"근": "1N"},+ "靴":{"화": "0N"},+ "靵":{"뉴": "1"},+ "靷":{"인": "0N"},+ "靺":{"말": "0N"},+ "靼":{"달": "1N"},+ "鞀":{"도": "1N"},+ "鞁":{"피": "1N"},+ "鞄":{"포": "1N"},+ "鞅":{"앙": "1N"},+ "鞋":{"혜": "0N"},+ "鞍":{"안": "0N"},+ "鞏":{"공": "0N"},+ "鞘":{"초": "1N"},+ "鞠":{"국": "0N"},+ "鞣":{"유": "1N"},+ "鞦":{"추": "1N"},+ "鞨":{"갈": "0N"},+ "鞫":{"국": "0N"},+ "鞬":{"건": "1N"},+ "鞭":{"편": "0N"},+ "鞱":{"도": "1N"},+ "鞴":{"비": "1N"},+ "鞸":{"필": "1N"},+ "鞹":{"곽": "1N"},+ "韁":{"강": "1N"},+ "韃":{"달": "1N"},+ "韆":{"천": "0N"},+ "韋":{"위": "0N"},+ "韌":{"인": "N"},+ "韍":{"불": "1N"},+ "韐":{"갑": "1"},+ "韓":{"한": "0E"},+ "韙":{"위": "1N"},+ "韜":{"도": "0N"},+ "韝":{"구": "1N"},+ "韞":{"온": "1N"},+ "韠":{"필": "1N"},+ "韡":{"위": "1N"},+ "韭":{"구": "1N"},+ "韮":{"구": "1"},+ "韱":{"섬": "1N"},+ "韲":{"제": "1N"},+ "音":{"음": "0E"},+ "韵":{"운": "1N"},+ "韶":{"소": "0N"},+ "韺":{"영": "1N"},+ "韻":{"운": "0E"},+ "韾":{"음": "N"},+ "響":{"향": "0E"},+ "頀":{"호": "0N"},+ "頁":{"혈": "0N"},+ "頂":{"정": "0E"},+ "頃":{"경": "0E"},+ "項":{"항": "0E"},+ "順":{"순": "0E"},+ "須":{"수": "0E"},+ "頊":{"욱": "0N"},+ "頌":{"송": "0E"},+ "頍":{"규": "1N"},+ "頎":{"기": "1N"},+ "頏":{"항": "1N"},+ "預":{"예": "0N"},+ "頑":{"완": "0N"},+ "頒":{"반": "0N"},+ "頓":{"돈": "0N"},+ "頖":{"반": "1N"},+ "頗":{"파": "0E"},+ "領":{"령": "0E", "영": "0"},+ "頞":{"알": "1N"},+ "頡":{"힐": "1N"},+ "頣":{"신": "1N"},+ "頤":{"이": "N"},+ "頦":{"해": "1N"},+ "頫":{"부": "1N"},+ "頭":{"두": "0E"},+ "頮":{"회": "1N"},+ "頰":{"협": "0N"},+ "頲":{"정": "N"},+ "頷":{"암": "1N"},+ "頸":{"경": "0N"},+ "頹":{"퇴": "0N"},+ "頻":{"빈": "0E"},+ "頼":{"뢰": "N"},+ "頿":{"자": "1N"},+ "顂":{"뢰": "1"},+ "顆":{"과": "0N"},+ "顇":{"췌": "1N"},+ "顈":{"경": "1N"},+ "顋":{"시": "1N"},+ "題":{"제": "0E"},+ "額":{"액": "0E"},+ "顎":{"악": "0N"},+ "顒":{"옹": "1N"},+ "顓":{"전": "1N"},+ "顔":{"안": "0E"},+ "顕":{"현": "N"},+ "願":{"원": "0E"},+ "顙":{"상": "1N"},+ "顚":{"전": "0N"},+ "顜":{"강": "N"},+ "類":{"류": "0E", "유": "0"},+ "顥":{"호": "0N"},+ "顦":{"초": "1N"},+ "顧":{"고": "0E"},+ "顫":{"전": "0N"},+ "顯":{"현": "0E"},+ "顰":{"빈": "1N"},+ "顱":{"로": "1N"},+ "顳":{"섭": "1N"},+ "顴":{"관": "1N"},+ "風":{"풍": "0E"},+ "颭":{"점": "1N"},+ "颯":{"삽": "0N"},+ "颱":{"태": "0N"},+ "颲":{"렬": "1N"},+ "颶":{"구": "1N"},+ "颺":{"양": "1N"},+ "颼":{"수": "1N"},+ "颿":{"범": "1N"},+ "飂":{"료": "1N"},+ "飄":{"표": "0N"},+ "飆":{"표": "N"},+ "飇":{"표": "0N"},+ "飉":{"료": "1N"},+ "飋":{"실": "1"},+ "飛":{"비": "0E"},+ "飜":{"번": "0E"},+ "食":{"식": "0E"},+ "飡":{"손": "0N"},+ "飢":{"기": "0E"},+ "飦":{"전": "1N"},+ "飧":{"손": "1N"},+ "飪":{"임": "1N"},+ "飫":{"어": "1N"},+ "飭":{"칙": "0N"},+ "飮":{"음": "0E"},+ "飯":{"반": "0E"},+ "飱":{"손": "1"},+ "飴":{"이": "0N"},+ "飻":{"철": "1N"},+ "飼":{"사": "0N"},+ "飽":{"포": "0E"},+ "飾":{"식": "0E"},+ "餃":{"교": "0N"},+ "餉":{"향": "0N"},+ "養":{"양": "0E"},+ "餌":{"이": "0"},+ "餐":{"찬": "0N"},+ "餒":{"뇌": "1N"},+ "餓":{"아": "0E"},+ "餔":{"포": "1N"},+ "餕":{"준": "1N"},+ "餘":{"여": "0E"},+ "餚":{"효": "1N"},+ "餞":{"전": "0N"},+ "餠":{"병": "0N"},+ "餦":{"장": "1N"},+ "餧":{"위": "1N"},+ "館":{"관": "0E"},+ "餪":{"난": "1N"},+ "餬":{"호": "1N"},+ "餮":{"철": "1N"},+ "餰":{"전": "1N"},+ "餱":{"후": "1N"},+ "餳":{"당": "1N"},+ "餹":{"당": "1N"},+ "餼":{"희": "1N"},+ "餽":{"궤": "1N"},+ "饂":{"온": "1"},+ "饅":{"만": "0N"},+ "饈":{"수": "1N"},+ "饉":{"근": "0N"},+ "饋":{"궤": "0N"},+ "饌":{"찬": "0N"},+ "饍":{"선": "0N"},+ "饐":{"의": "1N"},+ "饑":{"기": "0N"},+ "饒":{"요": "0N"},+ "饔":{"옹": "0N"},+ "饕":{"도": "1N"},+ "饗":{"향": "0N"},+ "饜":{"염": "1N"},+ "饞":{"참": "1N"},+ "首":{"수": "0E"},+ "馗":{"규": "1N"},+ "馘":{"괵": "1N"},+ "香":{"향": "0E"},+ "馜":{"니": "N"},+ "馝":{"필": "0N"},+ "馟":{"도": "N"},+ "馡":{"비": "N"},+ "馣":{"암": "1N"},+ "馥":{"복": "0N"},+ "馧":{"온": "N"},+ "馨":{"형": "0N"},+ "馪":{"빈": "N"},+ "馬":{"마": "0E"},+ "馭":{"어": "0N"},+ "馮":{"풍": "0N"},+ "馰":{"적": "1N"},+ "馱":{"타": "0N"},+ "馳":{"치": "0N"},+ "馴":{"순": "0N"},+ "馶":{"지": "N"},+ "馹":{"일": "0N"},+ "駁":{"박": "0N"},+ "駄":{"태": "1"},+ "駈":{"구": "1"},+ "駉":{"경": "1N"},+ "駏":{"거": "1N"},+ "駐":{"주": "0N"},+ "駑":{"노": "0N"},+ "駒":{"구": "0N"},+ "駕":{"가": "0N"},+ "駘":{"태": "1N"},+ "駙":{"부": "0N"},+ "駛":{"사": "1N"},+ "駜":{"필": "1N"},+ "駝":{"타": "0N"},+ "駞":{"타": "1N"},+ "駟":{"사": "0N"},+ "駢":{"변": "1N"},+ "駨":{"순": "1N"},+ "駪":{"신": "1N"},+ "駭":{"해": "0N"},+ "駮":{"박": "1N"},+ "駱":{"낙": "0", "락": "0N"},+ "駸":{"침": "1N"},+ "駺":{"랑": "N", "량": "N"},+ "駻":{"한": "1N"},+ "駽":{"현": "1N"},+ "駿":{"준": "0N"},+ "騁":{"빙": "0N"},+ "騂":{"성": "1N"},+ "騃":{"애": "1N"},+ "騄":{"록": "1"},+ "騅":{"추": "1N"},+ "騈":{"병": "0N"},+ "騋":{"래": "1N"},+ "騍":{"과": "1N"},+ "騎":{"기": "0E"},+ "騏":{"기": "0N"},+ "騑":{"비": "1N"},+ "騖":{"무": "1N"},+ "騘":{"총": "1"},+ "騙":{"편": "0N"},+ "騛":{"비": "1N"},+ "騫":{"건": "0N"},+ "騭":{"즐": "1N"},+ "騰":{"등": "0E"},+ "騵":{"원": "1N"},+ "騶":{"추": "0N"},+ "騷":{"소": "0E"},+ "騸":{"선": "1N"},+ "騾":{"라": "1N"},+ "驀":{"맥": "0N"},+ "驁":{"오": "1N"},+ "驂":{"참": "1N"},+ "驃":{"표": "0N"},+ "驄":{"총": "1N"},+ "驅":{"구": "0E"},+ "驊":{"화": "1N"},+ "驌":{"숙": "1N"},+ "驍":{"효": "0N"},+ "驎":{"린": "1N"},+ "驏":{"잔": "1N"},+ "驒":{"탄": "1N"},+ "驕":{"교": "0N"},+ "驗":{"험": "0E"},+ "驘":{"라": "1N"},+ "驚":{"경": "0E"},+ "驛":{"역": "0E"},+ "驟":{"취": "0N"},+ "驢":{"려": "0N"},+ "驤":{"양": "1N"},+ "驥":{"기": "0N"},+ "驩":{"환": "0N"},+ "驪":{"려": "0N", "여": "0"},+ "骨":{"골": "0E"},+ "骪":{"위": "1N"},+ "骰":{"투": "1N"},+ "骸":{"해": "0N"},+ "骹":{"교": "1N"},+ "骼":{"격": "1N"},+ "骿":{"변": "1N"},+ "髀":{"비": "1N"},+ "髆":{"박": "1N"},+ "髏":{"루": "1N"},+ "髑":{"촉": "1N"},+ "髓":{"수": "0N"},+ "體":{"체": "0E"},+ "髖":{"관": "1N"},+ "髗":{"로": "1N"},+ "高":{"고": "0E"},+ "髟":{"표": "1N"},+ "髡":{"곤": "1N"},+ "髣":{"방": "1N"},+ "髥":{"염": "0N"},+ "髦":{"모": "1N"},+ "髫":{"초": "1N"},+ "髭":{"자": "1N"},+ "髮":{"발": "0E"},+ "髰":{"체": "1N"},+ "髲":{"피": "1N"},+ "髴":{"불": "1N"},+ "髹":{"휴": "1N"},+ "髺":{"괄": "1N"},+ "髻":{"계": "1N"},+ "髽":{"좌": "1N"},+ "鬂":{"빈": "1"},+ "鬅":{"붕": "1N"},+ "鬆":{"송": "1N"},+ "鬊":{"순": "1N"},+ "鬋":{"전": "1N"},+ "鬍":{"호": "1N"},+ "鬐":{"기": "1N"},+ "鬒":{"진": "1N"},+ "鬖":{"삼": "1N"},+ "鬘":{"만": "1N"},+ "鬙":{"승": "1N"},+ "鬚":{"수": "0N"},+ "鬟":{"환": "1N"},+ "鬢":{"빈": "1N"},+ "鬣":{"렵": "1N"},+ "鬧":{"뇨": "N", "료": "0"},+ "鬨":{"홍": "1N"},+ "鬩":{"혁": "1N"},+ "鬪":{"투": "0E"},+ "鬮":{"구": "1N"},+ "鬯":{"창": "1N"},+ "鬱":{"울": "0N"},+ "鬲":{"격": "1N"},+ "鬺":{"상": "1N"},+ "鬼":{"귀": "0E"},+ "魁":{"괴": "0N"},+ "魂":{"혼": "0E"},+ "魃":{"발": "0N"},+ "魄":{"백": "0N"},+ "魅":{"매": "0N"},+ "魈":{"소": "1N"},+ "魋":{"추": "1N"},+ "魍":{"망": "1N"},+ "魎":{"량": "1N"},+ "魏":{"위": "0N"},+ "魑":{"리": "1N"},+ "魔":{"마": "0N"},+ "魘":{"염": "1N"},+ "魚":{"어": "0E"},+ "魦":{"사": "1N"},+ "魯":{"노": "0", "로": "0N"},+ "魴":{"방": "1N"},+ "鮀":{"타": "1N"},+ "鮃":{"평": "1N"},+ "鮎":{"점": "0N"},+ "鮐":{"태": "N"},+ "鮑":{"포": "0N"},+ "鮒":{"부": "1N"},+ "鮓":{"자": "1N"},+ "鮗":{"동": "1"},+ "鮟":{"안": "0N"},+ "鮧":{"제": "1N"},+ "鮨":{"지": "1N"},+ "鮪":{"유": "1N"},+ "鮫":{"교": "0N"},+ "鮭":{"해": "1N"},+ "鮮":{"선": "0E"},+ "鮹":{"소": "1N"},+ "鯁":{"경": "1N"},+ "鯆":{"포": "1N"},+ "鯉":{"리": "0N"},+ "鯊":{"사": "1N"},+ "鯔":{"치": "1N"},+ "鯖":{"청": "0N"},+ "鯛":{"조": "1N"},+ "鯢":{"예": "1N"},+ "鯤":{"곤": "0N"},+ "鯨":{"경": "0N"},+ "鯷":{"제": "1N"},+ "鰈":{"접": "1N"},+ "鰊":{"련": "1N"},+ "鰌":{"추": "1N"},+ "鰍":{"추": "0N"},+ "鰐":{"악": "0N"},+ "鰒":{"복": "0N"},+ "鰓":{"새": "1N"},+ "鰕":{"하": "0N"},+ "鰤":{"사": "1N"},+ "鰥":{"환": "0N"},+ "鰭":{"기": "1N"},+ "鰮":{"온": "1"},+ "鰯":{"약": "1"},+ "鰱":{"련": "1N"},+ "鰲":{"오": "0N"},+ "鰵":{"민": "1N"},+ "鰹":{"견": "1N"},+ "鰺":{"소": "1"},+ "鰻":{"만": "0N"},+ "鰾":{"표": "1N"},+ "鱇":{"강": "0N"},+ "鱉":{"별": "0N"},+ "鱏":{"심": "1N"},+ "鱒":{"준": "1N"},+ "鱓":{"선": "1N"},+ "鱗":{"린": "0N", "인": "0"},+ "鱠":{"회": "1N"},+ "鱣":{"전": "1N"},+ "鱧":{"례": "1N"},+ "鱸":{"로": "1N"},+ "鱻":{"선": "1N"},+ "鳥":{"조": "0E"},+ "鳦":{"을": "1N"},+ "鳧":{"부": "0N"},+ "鳩":{"구": "0N"},+ "鳳":{"봉": "0E"},+ "鳴":{"명": "0E"},+ "鳶":{"연": "0N"},+ "鴃":{"격": "1N"},+ "鴆":{"짐": "1N"},+ "鴇":{"보": "1N"},+ "鴈":{"안": "1N"},+ "鴉":{"아": "0N"},+ "鴌":{"봉": "1N"},+ "鴒":{"령": "1N"},+ "鴕":{"타": "1N"},+ "鴘":{"변": "1N"},+ "鴙":{"치": "1N"},+ "鴛":{"원": "0N"},+ "鴟":{"치": "1N"},+ "鴣":{"고": "1N"},+ "鴥":{"율": "N"},+ "鴦":{"앙": "0N"},+ "鴨":{"압": "0N"},+ "鴯":{"이": "N"},+ "鴰":{"괄": "1N"},+ "鴶":{"알": "1N"},+ "鴻":{"홍": "0E"},+ "鵁":{"교": "1N"},+ "鵂":{"휴": "1N"},+ "鵄":{"치": "1N"},+ "鵑":{"견": "0N"},+ "鵓":{"발": "1N"},+ "鵔":{"준": "1N"},+ "鵝":{"아": "0N"},+ "鵞":{"아": "1N"},+ "鵠":{"곡": "0N"},+ "鵡":{"무": "0N"},+ "鵦":{"록": "N"},+ "鵩":{"복": "1N"},+ "鵬":{"붕": "0N"},+ "鵯":{"필": "1N"},+ "鵰":{"조": "1N"},+ "鵲":{"작": "0N"},+ "鵷":{"원": "1N"},+ "鵻":{"추": "1N"},+ "鵾":{"곤": "1N"},+ "鶄":{"청": "1N"},+ "鶉":{"순": "1N"},+ "鶊":{"경": "N"},+ "鶖":{"추": "1N"},+ "鶚":{"악": "1N"},+ "鶡":{"갈": "1"},+ "鶤":{"곤": "1N"},+ "鶩":{"목": "0N"},+ "鶬":{"창": "1N"},+ "鶯":{"앵": "0N"},+ "鶴":{"학": "0E"},+ "鶵":{"추": "1N"},+ "鶸":{"약": "1N"},+ "鶹":{"류": "1N"},+ "鶻":{"골": "1N"},+ "鶿":{"자": "1N"},+ "鷁":{"익": "1N"},+ "鷂":{"요": "1N"},+ "鷄":{"계": "0E"},+ "鷇":{"구": "1N"},+ "鷓":{"자": "1N"},+ "鷖":{"예": "1N"},+ "鷗":{"구": "0N"},+ "鷙":{"지": "1N"},+ "鷦":{"초": "1N"},+ "鷩":{"별": "1N"},+ "鷪":{"앵": "1"},+ "鷫":{"숙": "1N"},+ "鷰":{"연": "1"},+ "鷱":{"고": "1N"},+ "鷲":{"취": "0N"},+ "鷳":{"한": "1N"},+ "鷸":{"휼": "0N"},+ "鷹":{"응": "0N"},+ "鷺":{"노": "0", "로": "0N"},+ "鷽":{"학": "1N"},+ "鷿":{"벽": "1N"},+ "鸇":{"전": "1N"},+ "鸏":{"몽": "1N"},+ "鸕":{"로": "1N"},+ "鸚":{"앵": "0N"},+ "鸛":{"관": "1N"},+ "鸜":{"구": "1N"},+ "鸞":{"난": "0", "란": "0N"},+ "鹵":{"로": "0N"},+ "鹷":{"령": "1N"},+ "鹹":{"함": "0N"},+ "鹺":{"차": "N"},+ "鹻":{"감": "1N"},+ "鹽":{"염": "0E"},+ "鹿":{"녹": "0", "록": "0E"},+ "麀":{"우": "1N"},+ "麂":{"궤": "1N"},+ "麄":{"추": "1"},+ "麋":{"미": "1N"},+ "麌":{"우": "1N"},+ "麏":{"균": "1N"},+ "麑":{"예": "1N"},+ "麒":{"기": "0N"},+ "麓":{"록": "0N"},+ "麗":{"려": "0E", "여": "0"},+ "麘":{"향": "N"},+ "麝":{"사": "0N"},+ "麞":{"장": "1N"},+ "麟":{"린": "0N", "인": "0"},+ "麤":{"추": "1N"},+ "麥":{"맥": "0E"},+ "麩":{"부": "1N"},+ "麪":{"면": "1N"},+ "麯":{"국": "1N"},+ "麴":{"국": "0N"},+ "麵":{"면": "0N"},+ "麻":{"마": "0E"},+ "麽":{"마": "1N"},+ "麾":{"휘": "0N"},+ "麿":{"마": "1"},+ "黃":{"황": "0E"},+ "黅":{"금": "1N"},+ "黌":{"횡": "1N"},+ "黍":{"서": "0N"},+ "黎":{"려": "0N", "여": "0"},+ "黏":{"점": "1N"},+ "黐":{"리": "1N"},+ "黑":{"흑": "0E"},+ "黔":{"검": "0N"},+ "黖":{"기": "1"},+ "默":{"묵": "0E"},+ "黚":{"겸": "1N"},+ "黛":{"대": "0N"},+ "黜":{"출": "0N"},+ "黝":{"유": "1N"},+ "點":{"점": "0E"},+ "黠":{"힐": "1N"},+ "黥":{"경": "1N"},+ "黨":{"당": "0E"},+ "黮":{"담": "1N"},+ "黯":{"암": "1N"},+ "黲":{"참": "1N"},+ "黴":{"미": "0N"},+ "黵":{"담": "1N"},+ "黶":{"염": "1N"},+ "黷":{"독": "1N"},+ "黺":{"분": "1N"},+ "黻":{"불": "1N"},+ "黼":{"보": "1N"},+ "黽":{"민": "1N"},+ "黿":{"원": "1N"},+ "鼀":{"축": "1N"},+ "鼂":{"조": "1N"},+ "鼄":{"주": "1N"},+ "鼇":{"오": "0N"},+ "鼈":{"별": "0N"},+ "鼉":{"타": "1N"},+ "鼊":{"벽": "1N"},+ "鼎":{"정": "0N"},+ "鼐":{"내": "1N"},+ "鼓":{"고": "0E"},+ "鼔":{"고": "N"},+ "鼗":{"도": "1N"},+ "鼙":{"비": "1N"},+ "鼠":{"서": "0N"},+ "鼢":{"분": "1N"},+ "鼫":{"석": "1N"},+ "鼬":{"유": "1N"},+ "鼯":{"오": "1N"},+ "鼴":{"언": "1N"},+ "鼸":{"겸": "1N"},+ "鼹":{"언": "1N"},+ "鼻":{"비": "0E"},+ "鼾":{"한": "1N"},+ "齊":{"제": "0E"},+ "齋":{"재": "0N"},+ "齎":{"재": "0N"},+ "齒":{"치": "0E"},+ "齔":{"친": "1"},+ "齕":{"흘": "1N"},+ "齗":{"은": "1N"},+ "齟":{"저": "0N"},+ "齠":{"초": "1N"},+ "齡":{"령": "0N"},+ "齦":{"간": "1N"},+ "齧":{"설": "0N"},+ "齩":{"교": "1N"},+ "齪":{"착": "0N"},+ "齫":{"곤": "1N"},+ "齬":{"어": "0N"},+ "齲":{"우": "1N"},+ "齶":{"악": "1N"},+ "齷":{"악": "0N"},+ "龍":{"룡": "0E", "용": "0"},+ "龎":{"롱": "1"},+ "龐":{"방": "0N"},+ "龑":{"엄": "N"},+ "龒":{"룡": "1N"},+ "龔":{"공": "1N"},+ "龕":{"감": "0N"},+ "龜":{"구": "0EN", "귀": "0N", "균": "0N"},+ "龝":{"추": "1N"},+ "龠":{"약": "1N"},+ "龢":{"화": "1N"},+ "龥":{"유": "1N"},+ "豈":{"개": "0"},+ "更":{"갱": "0"},+ "車":{"거": "0"},+ "賈":{"고": "0"},+ "滑":{"골": "0"},+ "串":{"관": "0"},+ "句":{"귀": "0"},+ "龜":{"귀": "0"},+ "龜":{"균": "0"},+ "契":{"글": "0"},+ "金":{"금": "0"},+ "喇":{"나": "0"},+ "奈":{"나": "0"},+ "懶":{"나": "0"},+ "癩":{"나": "0"},+ "羅":{"나": "0"},+ "蘿":{"나": "0"},+ "螺":{"나": "0"},+ "裸":{"나": "0"},+ "邏":{"나": "0"},+ "樂":{"낙": "0"},+ "洛":{"낙": "0"},+ "烙":{"낙": "0"},+ "珞":{"낙": "0"},+ "落":{"낙": "0"},+ "酪":{"낙": "0"},+ "駱":{"낙": "0"},+ "亂":{"난": "0"},+ "卵":{"난": "0"},+ "欄":{"난": "0"},+ "爛":{"난": "0"},+ "蘭":{"난": "0"},+ "鸞":{"난": "0"},+ "嵐":{"남": "0"},+ "濫":{"남": "0"},+ "藍":{"남": "0"},+ "襤":{"남": "0"},+ "拉":{"납": "0"},+ "臘":{"납": "0"},+ "蠟":{"납": "0"},+ "廊":{"낭": "0"},+ "朗":{"낭": "0"},+ "浪":{"낭": "0"},+ "狼":{"낭": "0"},+ "郎":{"낭": "0"},+ "來":{"내": "0"},+ "冷":{"냉": "0"},+ "勞":{"노": "0"},+ "擄":{"노": "0"},+ "櫓":{"노": "0"},+ "爐":{"노": "0"},+ "盧":{"노": "0"},+ "老":{"노": "0"},+ "蘆":{"노": "0"},+ "虜":{"노": "0"},+ "路":{"노": "0"},+ "露":{"노": "0"},+ "魯":{"노": "0"},+ "鷺":{"노": "0"},+ "碌":{"녹": "0"},+ "祿":{"녹": "0"},+ "綠":{"녹": "0"},+ "菉":{"녹": "0"},+ "錄":{"녹": "0"},+ "鹿":{"녹": "0"},+ "論":{"논": "0"},+ "壟":{"농": "0"},+ "弄":{"농": "0"},+ "籠":{"농": "0"},+ "聾":{"농": "0"},+ "牢":{"뇌": "0"},+ "磊":{"뇌": "0"},+ "賂":{"뇌": "0"},+ "雷":{"뇌": "0"},+ "壘":{"누": "0"},+ "屢":{"누": "0"},+ "樓":{"누": "0"},+ "淚":{"누": "0"},+ "漏":{"누": "0"},+ "累":{"누": "0"},+ "縷":{"누": "0"},+ "陋":{"누": "0"},+ "勒":{"늑": "0"},+ "肋":{"늑": "0"},+ "凜":{"늠": "0"},+ "凌":{"능": "0"},+ "稜":{"능": "0"},+ "綾":{"능": "0"},+ "菱":{"능": "0"},+ "陵":{"능": "0"},+ "讀":{"두": "0"},+ "拏":{"라": "0"},+ "樂":{"락": "0"},+ "諾":{"락": "0"},+ "丹":{"란": "0"},+ "寧":{"령": "0"},+ "怒":{"로": "0"},+ "率":{"률": "0"},+ "異":{"리": "0"},+ "北":{"배": "0"},+ "磻":{"번": "0"},+ "便":{"변": "0"},+ "復":{"부": "0"},+ "不":{"불": "0"},+ "泌":{"비": "0"},+ "數":{"삭": "0"},+ "索":{"삭": "0"},+ "參":{"삼": "0"},+ "塞":{"색": "0"},+ "省":{"생": "0"},+ "葉":{"섭": "0"},+ "說":{"세": "0"},+ "殺":{"쇄": "0"},+ "辰":{"신": "0"},+ "沈":{"심": "0"},+ "拾":{"십": "0"},+ "若":{"야": "0"},+ "掠":{"약": "0"},+ "略":{"약": "0"},+ "亮":{"양": "0"},+ "兩":{"양": "0"},+ "凉":{"양": "0"},+ "梁":{"양": "0"},+ "糧":{"양": "0"},+ "良":{"양": "0"},+ "諒":{"양": "0"},+ "量":{"양": "0"},+ "勵":{"여": "0"},+ "呂":{"여": "0"},+ "女":{"여": "0"},+ "廬":{"여": "0"},+ "旅":{"여": "0"},+ "濾":{"여": "0"},+ "礪":{"여": "0"},+ "閭":{"여": "0"},+ "驪":{"여": "0"},+ "麗":{"여": "0"},+ "黎":{"여": "0"},+ "力":{"역": "0"},+ "曆":{"역": "0"},+ "歷":{"역": "0"},+ "轢":{"역": "0"},+ "年":{"연": "0"},+ "憐":{"연": "0"},+ "戀":{"연": "0"},+ "撚":{"연": "0"},+ "漣":{"연": "0"},+ "煉":{"연": "0"},+ "璉":{"연": "0"},+ "秊":{"연": "0"},+ "練":{"연": "0"},+ "聯":{"연": "0"},+ "輦":{"연": "0"},+ "蓮":{"연": "0"},+ "連":{"연": "0"},+ "鍊":{"연": "0"},+ "列":{"열": "0"},+ "劣":{"열": "0"},+ "咽":{"열": "0"},+ "烈":{"열": "0"},+ "裂":{"열": "0"},+ "說":{"열": "0"},+ "廉":{"염": "0"},+ "念":{"염": "0"},+ "捻":{"염": "0"},+ "殮":{"염": "0"},+ "簾":{"염": "0"},+ "獵":{"엽": "0"},+ "令":{"영": "0"},+ "囹":{"영": "0"},+ "寧":{"영": "0"},+ "嶺":{"영": "0"},+ "怜":{"영": "0"},+ "玲":{"영": "0"},+ "瑩":{"영": "0"},+ "羚":{"영": "0"},+ "聆":{"영": "0"},+ "鈴":{"영": "0"},+ "零":{"영": "0"},+ "靈":{"영": "0"},+ "領":{"영": "0"},+ "例":{"예": "0"},+ "禮":{"예": "0"},+ "醴":{"예": "0"},+ "隸":{"예": "0"},+ "惡":{"오": "0"},+ "了":{"요": "0"},+ "僚":{"요": "0"},+ "寮":{"요": "0"},+ "尿":{"요": "0"},+ "料":{"요": "0"},+ "樂":{"요": "0"},+ "燎":{"요": "0"},+ "療":{"요": "0"},+ "蓼":{"요": "0"},+ "遼":{"요": "0"},+ "龍":{"용": "0"},+ "暈":{"운": "0"},+ "阮":{"원": "0"},+ "劉":{"유": "0"},+ "杻":{"유": "0"},+ "柳":{"유": "0"},+ "流":{"유": "0"},+ "溜":{"유": "0"},+ "琉":{"유": "0"},+ "留":{"유": "0"},+ "硫":{"유": "0"},+ "紐":{"유": "0"},+ "類":{"유": "0"},+ "六":{"육": "0"},+ "戮":{"육": "0"},+ "陸":{"육": "0"},+ "倫":{"윤": "0"},+ "崙":{"윤": "0"},+ "淪":{"윤": "0"},+ "輪":{"윤": "0"},+ "律":{"율": "0"},+ "慄":{"율": "0"},+ "栗":{"율": "0"},+ "率":{"율": "0"},+ "隆":{"융": "0"},+ "利":{"이": "0"},+ "吏":{"이": "0"},+ "履":{"이": "0"},+ "易":{"이": "0"},+ "李":{"이": "0"},+ "梨":{"이": "0"},+ "泥":{"이": "0"},+ "理":{"이": "0"},+ "痢":{"이": "0"},+ "罹":{"이": "0"},+ "裏":{"이": "0"},+ "裡":{"이": "0"},+ "里":{"이": "0"},+ "離":{"이": "0"},+ "匿":{"익": "0"},+ "溺":{"익": "0"},+ "吝":{"인": "0"},+ "燐":{"인": "0"},+ "璘":{"인": "0"},+ "藺":{"인": "0"},+ "隣":{"인": "0"},+ "鱗":{"인": "0"},+ "麟":{"인": "0"},+ "林":{"임": "0"},+ "淋":{"임": "0"},+ "臨":{"임": "0"},+ "立":{"입": "0"},+ "笠":{"입": "0"},+ "粒":{"입": "0"},+ "狀":{"장": "0"},+ "炙":{"적": "0"},+ "識":{"지": "0"},+ "什":{"집": "0"},+ "茶":{"차": "0"},+ "刺":{"척": "0"},+ "切":{"체": "0"},+ "度":{"탁": "0"},+ "拓":{"탁": "0"},+ "糖":{"탕": "0"},+ "宅":{"택": "0"},+ "洞":{"통": "0"},+ "暴":{"포": "0"},+ "輻":{"폭": "0"},+ "行":{"항": "0"},+ "降":{"항": "0"},+ "見":{"현": "0"},+ "廓":{"확": "0"},+ "郞":{"낭": "0"},+ "隷":{"예": "0"},+ "𠃗":{"울": "N"},+ "𠄬":{"조": "N"},+ "𠗊":{"경": "N"},+ "𠦄":{"훼": "N"},+ "𡅕":{"희": "N"},+ "𡊍":{"술": "N"},+ "𡖔":{"나": "N"},+ "𡜧":{"세": "N"},+ "𡽜":{"한": "N"},+ "𢒰":{"욱": "N"},+ "𢓭":{"준": "N"},+ "𢥏":{"영": "N"},+ "𢱯":{"람": "N"},+ "𢻠":{"리": "N"},+ "𣃽":{"나": "N"},+ "𣍃":{"인": "N"},+ "𣘻":{"다": "N"},+ "𣫙":{"예": "N"},+ "𤋱":{"훈": "N"},+ "𤎝":{"안": "N"},+ "𤣰":{"보": "N"},+ "𤨁":{"진": "N"},+ "𤨒":{"은": "N"},+ "𥁕":{"온": "N"},+ "𥌾":{"응": "N"},+ "𥎵":{"지": "N"},+ "𥏾":{"지": "N"},+ "𥠲":{"률": "N"},+ "𥠺":{"온": "N"},+ "𥡴":{"계": "N"},+ "𥥸":{"다": "N"},+ "𥮗":{"국": "N"},+ "𥹄":{"미": "N"},+ "𦁗":{"섭": "N"},+ "𦖤":{"성": "N"},+ "𦟘":{"인": "N"},+ "𧅄":{"기": "N"},+ "𧗿":{"솔": "N"},+ "𧘥":{"뉴": "N"},+ "𧩑":{"서": "N"},+ "𧬂":{"하": "N"},+ "𧹽":{"혁": "N"},+ "𧼛":{"래": "N"},+ "𨏶":{"련": "N"},+ "𨓜":{"일": "N"},+ "𨶊":{"준": "N"},+ "𨶡":{"은": "N"},+ "𩇕":{"정": "N"},+ "𩇣":{"슬": "N"},+ "𩓞":{"정": "N"},+ "𩔉":{"민": "N"},+ "𩠻":{"별": "N"},+ "𪊭":{"린": "N"},+ "𪓐":{"초": "N"},+ "𪙤":{"은": "N"},+ "𬄕":{"집": "N"},+ "𬟓":{"훈": "N"},+ "𮕩":{"쇠": "E"}+}
+ test/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ test/Text/Seonbi/FacadeSpec.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+module Text.Seonbi.FacadeSpec (spec) where++import Data.String (IsString)++import Test.Hspec++import Text.Seonbi.Facade++input :: (IsString a, Monoid a) => a+input =+ "<blockquote><p>아이들에게 하로의 乾燥한 學課로<br>" <>+ "해말간 倦怠가 깃들고,<br>" <>+ ""矛盾" 두자를 理解치 못하도록<br>" <>+ "머리가 單純하였구나.</p>" <>+ "</blockquote><p>尹東柱 <이런날></p>"++output :: (IsString a, Monoid a) => a+output =+ "<blockquote><p>아이들에게 하로의 건조한 학과로<br>" <>+ "해말간 권태가 깃들고,<br>" <>+ "“모순” 두자를 이해치 못하도록<br>" <>+ "머리가 단순하였구나.</p>" <>+ "</blockquote><p>윤동주 〈이런날〉</p>"++spec :: Spec+spec =+ specify "transformHtmlLazyText" $ do+ let noOp = Configuration+ { quote = Nothing+ , cite = Nothing+ , arrow = Nothing+ , ellipsis = False+ , emDash = False+ , hanja = Nothing+ , xhtml = False+ , debugLogger = Nothing+ }+ transformHtmlLazyText noOp input `shouldBe` Just input+ transformHtmlLazyText ko_KR input `shouldBe` Just output
+ test/Text/Seonbi/HangulSpec.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+module Text.Seonbi.HangulSpec (spec) where++import Test.Hspec++import Text.Seonbi.Hangul+++spec :: Spec+spec = do+ specify "isHangulSyllable" $ do+ '가' `shouldSatisfy` isHangulSyllable+ '글' `shouldSatisfy` isHangulSyllable+ 'A' `shouldNotSatisfy` isHangulSyllable+ '?' `shouldNotSatisfy` isHangulSyllable+ '字' `shouldNotSatisfy` isHangulSyllable+ describe "toJamoTriple" $ do+ it "returns only initial cosonant and vowel if there is no batchim" $+ toJamoTriple '가' `shouldBe` Just ('ᄀ', 'ᅡ', Nothing)+ it "returns all of triple if there is a batchim" $ do+ toJamoTriple '글' `shouldBe` Just ('ᄀ', 'ᅳ', Just 'ᆯ')+ toJamoTriple '를' `shouldBe` Just ('ᄅ', 'ᅳ', Just 'ᆯ')+ it "returns Nothing for non-Hangul letters" $ do+ toJamoTriple 'A' `shouldBe` Nothing+ toJamoTriple '?' `shouldBe` Nothing+ toJamoTriple '字' `shouldBe` Nothing+ specify "fromJamoTriple" $ do+ fromJamoTriple ('ᄀ', 'ᅡ', Nothing) `shouldBe` Just '가'+ fromJamoTriple ('ᄀ', 'ᅳ', Just 'ᆯ') `shouldBe` Just '글'+ fromJamoTriple ('ᄅ', 'ᅳ', Just 'ᆯ') `shouldBe` Just '를'+ fromJamoTriple ('ᄓ', 'ᅳ', Nothing) `shouldBe` Nothing+ fromJamoTriple ('ᄀ', 'ᅶ', Nothing) `shouldBe` Nothing+ fromJamoTriple ('ᄀ', 'ᅳ', Just 'ᅡ') `shouldBe` Nothing+ fromJamoTriple ('ᄀ', 'ᅳ', Just 'ᇇ') `shouldBe` Nothing
+ test/Text/Seonbi/HanjaSpec.hs view
@@ -0,0 +1,341 @@+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+module Text.Seonbi.HanjaSpec (spec) where++import Test.Hspec++import Text.Seonbi.Hanja+import Text.Seonbi.Html++inputFixture :: [HtmlEntity]+inputFixture =+ [ HtmlStartTag [] H1 ""+ , HtmlText [H1] "異蹟"+ , HtmlEndTag [] H1+ , HtmlStartTag [] P ""+ , HtmlText [P] "발에 터분한 것을 다 빼어 바리고"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "黃昏이 湖水우로 걸어 오듯이"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "나도 삽분삽분 걸어 보리이까?"+ , HtmlEndTag [] P+ , HtmlStartTag [] P ""+ , HtmlText [P] "내사 이 湖水가로"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "부르는 이 없이"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "불리워 온것은"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "참말 異蹟이외다."+ , HtmlEndTag [] P+ , HtmlStartTag [] P ""+ , HtmlText [P] "오늘 따라"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "戀情, 自惚, 猜忌, 이것들이"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "자꼬 金메달처럼 만져지는구려"+ , HtmlEndTag [] P+ , HtmlStartTag [] P ""+ , HtmlText [P] "하나, 내 모든 것을 餘念없이"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "물결에 써서 보내려니"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "당신은 湖面으로 나를 불러 내소서."+ , HtmlEndTag [] P+ ]++outputFixture :: [HtmlEntity]+outputFixture =+ [ HtmlStartTag [] H1 ""+ , HtmlText [H1] "리적"+ , HtmlEndTag [] H1+ , HtmlStartTag [] P ""+ , HtmlText [P] "발에 터분한 것을 다 빼어 바리고"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "황혼이 호수우로 걸어 오듯이"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "나도 삽분삽분 걸어 보리이까?"+ , HtmlEndTag [] P+ , HtmlStartTag [] P ""+ , HtmlText [P] "내사 이 호수가로"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "부르는 이 없이"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "불리워 온것은"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "참말 리적이외다."+ , HtmlEndTag [] P+ , HtmlStartTag [] P ""+ , HtmlText [P] "오늘 따라"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "련정, 자홀, 시기, 이것들이"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "자꼬 금메달처럼 만져지는구려"+ , HtmlEndTag [] P+ , HtmlStartTag [] P ""+ , HtmlText [P] "하나, 내 모든 것을 여념없이"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "물결에 써서 보내려니"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "당신은 호면으로 나를 불러 내소서."+ , HtmlEndTag [] P+ ]++outputWithInitialSoundLawFixture :: [HtmlEntity]+outputWithInitialSoundLawFixture =+ [ HtmlStartTag [] H1 ""+ , HtmlText [H1] "이적"+ , HtmlEndTag [] H1+ , HtmlStartTag [] P ""+ , HtmlText [P] "발에 터분한 것을 다 빼어 바리고"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "황혼이 호수우로 걸어 오듯이"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "나도 삽분삽분 걸어 보리이까?"+ , HtmlEndTag [] P+ , HtmlStartTag [] P ""+ , HtmlText [P] "내사 이 호수가로"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "부르는 이 없이"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "불리워 온것은"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "참말 이적이외다."+ , HtmlEndTag [] P+ , HtmlStartTag [] P ""+ , HtmlText [P] "오늘 따라"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "연정, 자홀, 시기, 이것들이"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "자꼬 금메달처럼 만져지는구려"+ , HtmlEndTag [] P+ , HtmlStartTag [] P ""+ , HtmlText [P] "하나, 내 모든 것을 여념없이"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "물결에 써서 보내려니"+ , HtmlStartTag [P] BR "", HtmlEndTag [P] BR+ , HtmlText [P] "당신은 호면으로 나를 불러 내소서."+ , HtmlEndTag [] P+ ]++spec :: Spec+spec = do+ describe "phoneticizeHanjaChar" $ do+ it "returns the input as is if not a Hanja character" $ do+ phoneticizeHanjaChar 'A' `shouldBe` 'A'+ phoneticizeHanjaChar '가' `shouldBe` '가'+ it "returns the most frequent way to read" $ do+ phoneticizeHanjaChar '金' `shouldBe` '금'+ phoneticizeHanjaChar '北' `shouldBe` '북'+ it "does not follow Initial Sound Law" $ do+ phoneticizeHanjaChar '六' `shouldBe` '륙'+ phoneticizeHanjaChar '禮' `shouldBe` '례'+ describe "phoneticizeHanjaWord" $ do+ it "returns the input as is if there are no hanja at all" $ do+ phoneticizeHanjaWord "foo" `shouldBe` "foo"+ phoneticizeHanjaWord "테스트" `shouldBe` "테스트"+ it "transforms hanja chars into the corresponding hangul readings" $ do+ phoneticizeHanjaWord "漢字" `shouldBe` "한자"+ phoneticizeHanjaWord "言文" `shouldBe` "언문"+ phoneticizeHanjaWord "餘念" `shouldBe` "여념"+ phoneticizeHanjaWord "來日" `shouldBe` "래일"+ phoneticizeHanjaWord "未來" `shouldBe` "미래"+ phoneticizeHanjaWord "良質" `shouldBe` "량질"+ phoneticizeHanjaWord "力量" `shouldBe` "력량"+ describe "phoneticizeHanjaWordWithInitialSoundLaw" $ do+ let phone = phoneticizeHanjaWordWithInitialSoundLaw+ it "returns the input as is if there are no hanja at all" $ do+ phone "foo" `shouldBe` "foo"+ phone "테스트" `shouldBe` "테스트"+ it "transforms hanja chars into the corresponding Hangul readings" $ do+ phone "漢字" `shouldBe` "한자"+ phone "言文" `shouldBe` "언문"+ phone "餘念" `shouldBe` "여념"+ phone "未來" `shouldBe` "미래"+ phone "法律" `shouldBe` "법률"+ phone "一列" `shouldBe` "일렬"+ it "converts the first letter according to Initial Sound Law" $ do+ phone "來日" `shouldBe` "내일"+ phone "良質" `shouldBe` "양질"+ phone "力量" `shouldBe` "역량"+ it ("converts a letter followed by no batchim or nieun (N) according "+ ++ "to Initial Sound Law") $ do+ phone "羅列" `shouldBe` "나열"+ phone "序列" `shouldBe` "서열"+ phone "義烈" `shouldBe` "의열"+ phone "規律" `shouldBe` "규율"+ phone "煨栗" `shouldBe` "외율"+ phone "自律" `shouldBe` "자율"+ phone "卑劣" `shouldBe` "비열"+ phone "優劣" `shouldBe` "우열"+ phone "熾烈" `shouldBe` "치열"+ phone "比率" `shouldBe` "비율"+ phone "利率" `shouldBe` "이율"+ phone "棗栗" `shouldBe` "조율"+ phone "分裂" `shouldBe` "분열"+ phone "前列" `shouldBe` "전열"+ phone "百分率" `shouldBe` "백분율"+ phone "韻律" `shouldBe` "운율"+ phone "煥率" `shouldBe` "환율"+ phone "分列" `shouldBe` "분열"+ phone "先烈" `shouldBe` "선열"+ phone "賤劣" `shouldBe` "천열"+ phone "旋律" `shouldBe` "선율"+ phone "戰慄" `shouldBe` "전율"+ it "converts all hanja digits according to Initial Sound Law" $ do+ phone "千九百八十六年" `shouldBe` "천구백팔십육년"+ phone "第六共和國" `shouldBe` "제육공화국"+ phone "拾萬圓" `shouldBe` "십만원"+ phone "參佰拾圓" `shouldBe` "삼백십원"+ phone "仟參佰圓" `shouldBe` "천삼백원"+ describe "withDictionary" $ do+ let dict =+ [ ("標識", "표지")+ , ("毛澤東", "마오쩌둥")+ , ("交通", "교통")+ ]+ let phone = withDictionary dict phoneticizeHanjaWordWithInitialSoundLaw+ it "replaces Sino-Korean words with hangul letters in a dictionary" $ do+ phone "標識" `shouldBe` "표지"+ phone "毛澤東" `shouldBe` "마오쩌둥"+ phone "交通標識" `shouldBe` "교통표지"+ it "uses a fallback phoneticizer for unknown morphemes" $+ phone "知識" `shouldBe` "지식"+ it "uses a fallback phoneticizer for unknown prefixes" $+ phone "安全標識" `shouldBe` "안전표지"+ it "uses a fallback phoneticizer for unknown suffixes" $ do+ phone "毛澤東語錄" `shouldBe` "마오쩌둥어록"+ phone "毛澤東理論" `shouldBe` "마오쩌둥이론"+ describe "phoneticizeHanja" $ do+ specify "without initial sound law" $ do+ let conf = def { phoneticizer = phoneticizeHanjaWord }+ normalizeText (phoneticizeHanja conf inputFixture)+ `shouldBe` normalizeText outputFixture+ specify "with initial sound law" $ do+ let conf = def+ { phoneticizer = phoneticizeHanjaWordWithInitialSoundLaw+ }+ let phone = normalizeText . phoneticizeHanja conf+ phone inputFixture `shouldBe`+ normalizeText outputWithInitialSoundLawFixture+ phone [HtmlText [] "1996年 그들이 地球를 支配했을 때"] `shouldBe`+ [HtmlText [] "1996년 그들이 지구를 지배했을 때"]+ specify "with hanjaInParentheses renderer" $ do+ let conf = def { wordRenderer = hanjaInParentheses }+ let phone = normalizeText . phoneticizeHanja conf+ phone [HtmlText [] "1996年 그들이 地球를 支配했을 때"] `shouldBe`+ [HtmlText [] "1996년(年) 그들이 지구(地球)를 지배(支配)했을 때"]+ specify "with hanjaInRuby renderer" $ do+ let conf = def { wordRenderer = hanjaInRuby }+ let phone = normalizeText . phoneticizeHanja conf+ phone [HtmlText [] "1996年 그들이 地球를 支配했을 때"] `shouldBe`+ [ HtmlText [] "1996"+ , HtmlStartTag [] Ruby ""+ , HtmlText [Ruby] "年"+ , HtmlStartTag [Ruby] RP ""+ , HtmlText [Ruby, RP] "("+ , HtmlEndTag [Ruby] RP+ , HtmlStartTag [Ruby] RT ""+ , HtmlText [Ruby, RT] "년"+ , HtmlEndTag [Ruby] RT+ , HtmlStartTag [Ruby] RP ""+ , HtmlText [Ruby, RP] ")"+ , HtmlEndTag [Ruby] RP+ , HtmlEndTag [] Ruby+ , HtmlText [] " 그들이 "+ , HtmlStartTag [] Ruby ""+ , HtmlText [Ruby] "地球"+ , HtmlStartTag [Ruby] RP ""+ , HtmlText [Ruby, RP] "("+ , HtmlEndTag [Ruby] RP+ , HtmlStartTag [Ruby] RT ""+ , HtmlText [Ruby, RT] "지구"+ , HtmlEndTag [Ruby] RT+ , HtmlStartTag [Ruby] RP ""+ , HtmlText [Ruby, RP] ")"+ , HtmlEndTag [Ruby] RP+ , HtmlEndTag [] Ruby+ , HtmlText [] "를 "+ , HtmlStartTag [] Ruby ""+ , HtmlText [Ruby] "支配"+ , HtmlStartTag [Ruby] RP ""+ , HtmlText [Ruby, RP] "("+ , HtmlEndTag [Ruby] RP+ , HtmlStartTag [Ruby] RT ""+ , HtmlText [Ruby, RT] "지배"+ , HtmlEndTag [Ruby] RT+ , HtmlStartTag [Ruby] RP ""+ , HtmlText [Ruby, RP] ")"+ , HtmlEndTag [Ruby] RP+ , HtmlEndTag [] Ruby+ , HtmlText [] "했을 때"+ ]+ it "disambiguate homophones" $ do+ let conf = def+ { wordRenderer = hangulOnly+ , homophoneRenderer = hanjaInParentheses+ }+ let phone = normalizeText . phoneticizeHanja conf+ let input =+ [ HtmlStartTag [] P ""+ , HtmlText [P] "同音 異義語 例: 連霸와 連敗"+ , HtmlEndTag [] P+ ]+ phone input `shouldBe` normalizeText+ [ HtmlStartTag [] P ""+ , HtmlText [P] "동음 이의어 예: 연패(連霸)와 연패(連敗)"+ , HtmlEndTag [] P+ ]+ it "does not transform numeral-only words" $ do+ let conf = def { wordRenderer = hanjaInParentheses }+ let phone = normalizeText . phoneticizeHanja conf+ phone [HtmlText [] "4·19革命"] `shouldBe`+ [HtmlText [] "4·19혁명(革命)"]+ phone [HtmlText [] "1987年10月29日"] `shouldBe`+ [HtmlText [] "1987년(年)10월(月)29일(日)"]+ it "transforms hanja characters in HTML entities" $ do+ let phone = normalizeText . phoneticizeHanja def+ phone [HtmlText [] "<1996年 그들이 地球를 支配했을 때>"]+ `shouldBe`+ [HtmlText [] "<1996년 그들이 지구를 지배했을 때>"]+ it "transforms nothing in preserved tags" $ do+ let phone = normalizeText . phoneticizeHanja def+ phone [HtmlText [Pre] "1996年 그들이 地球를 支配했을 때"] `shouldBe`+ [HtmlText [Pre] "1996年 그들이 地球를 支配했을 때"]+ describe "convertInitialSoundLaw" $ do+ specify "녀, 뇨, 뉴, 니 should be 여, 요, 유, 이" $ do+ convertInitialSoundLaw '녀' `shouldBe` '여'+ convertInitialSoundLaw '뉴' `shouldBe` '유'+ convertInitialSoundLaw '년' `shouldBe` '연'+ convertInitialSoundLaw '니' `shouldBe` '이'+ convertInitialSoundLaw '뇨' `shouldBe` '요'+ convertInitialSoundLaw '닉' `shouldBe` '익'+ specify "랴, 려, 례, 료, 류, 리 should be 야, 여, 예, 요, 유, 이" $ do+ convertInitialSoundLaw '량' `shouldBe` '양'+ convertInitialSoundLaw '룡' `shouldBe` '용'+ convertInitialSoundLaw '력' `shouldBe` '역'+ convertInitialSoundLaw '류' `shouldBe` '유'+ convertInitialSoundLaw '례' `shouldBe` '예'+ convertInitialSoundLaw '림' `shouldBe` '임'+ specify "라, 래, 로, 뢰, 루, 르 should be 나, 내, 노, 뇌, 누, 느" $ do+ convertInitialSoundLaw '락' `shouldBe` '낙'+ convertInitialSoundLaw '뢰' `shouldBe` '뇌'+ convertInitialSoundLaw '래' `shouldBe` '내'+ convertInitialSoundLaw '루' `shouldBe` '누'+ convertInitialSoundLaw '로' `shouldBe` '노'+ convertInitialSoundLaw '릉' `shouldBe` '능'+ specify "revertInitialSoundLaw" $ do+ revertInitialSoundLaw '여' `shouldBe` ['녀', '려']+ revertInitialSoundLaw '유' `shouldBe` ['뉴', '류']+ revertInitialSoundLaw '연' `shouldBe` ['년', '련']+ revertInitialSoundLaw '이' `shouldBe` ['니', '리']+ revertInitialSoundLaw '요' `shouldBe` ['뇨', '료']+ revertInitialSoundLaw '입' `shouldBe` ['닙', '립']+ revertInitialSoundLaw '양' `shouldBe` ['량']+ revertInitialSoundLaw '예' `shouldBe` ['례']+ revertInitialSoundLaw '낙' `shouldBe` ['락']+ revertInitialSoundLaw '뇌' `shouldBe` ['뢰']+ revertInitialSoundLaw '내' `shouldBe` ['래']+ revertInitialSoundLaw '누' `shouldBe` ['루']+ revertInitialSoundLaw '노' `shouldBe` ['로']+ revertInitialSoundLaw '능' `shouldBe` ['릉']
+ test/Text/Seonbi/Html/ClipperSpec.hs view
@@ -0,0 +1,186 @@+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+module Text.Seonbi.Html.ClipperSpec (spec) where++import Control.Monad++import Data.Text+import Test.Hspec++import Text.Seonbi.Html.Clipper+import Text.Seonbi.Html.Entity+import Text.Seonbi.Html.Tag++spec :: Spec+spec = do+ describe "clipPrefixText" $ do+ it "returns Nothing if entities are empty and a prefix is not empty" $+ clipPrefixText "foo" [] `shouldBe` Nothing+ it "returns Nothing if the first entity is not an HtmlText" $+ forM_ (["", "foo"] :: [Text]) $ \ prefix -> do+ clipPrefixText prefix+ [ HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ ] `shouldBe` Nothing+ clipPrefixText prefix+ [ HtmlComment [] "foo"+ , HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ ] `shouldBe` Nothing+ clipPrefixText prefix [HtmlEndTag [] P] `shouldBe` Nothing+ clipPrefixText prefix [HtmlCdata [] "foo"] `shouldBe` Nothing+ it "returns Just [] if entities are empty and a prefix is empty too" $+ clipPrefixText "" [] `shouldBe` Just []+ it "returns entities with the prefix text dropped" $ do+ clipPrefixText "foo"+ [ HtmlText [] "foobar"+ , HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ ]+ `shouldBe` Just+ [ HtmlText [] "bar"+ , HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ ]+ clipPrefixText "foo"+ [ HtmlText [] "foo"+ , HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ ]+ `shouldBe` Just+ [ HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ ]+ it "ignores HtmlComment entities but preseves them" $ do+ clipPrefixText "foo"+ [ HtmlComment [] "comment"+ , HtmlText [] "foobar"+ , HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ ]+ `shouldBe` Just+ [ HtmlComment [] "comment"+ , HtmlText [] "bar"+ , HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ ]+ clipPrefixText "foo"+ [ HtmlComment [] "comment"+ , HtmlText [] "foo"+ , HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ ]+ `shouldBe` Just+ [ HtmlComment [] "comment"+ , HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ ]++ describe "clipSuffixText" $ do+ it "returns Nothing if entities are empty and a suffix is not empty" $+ clipSuffixText "foo" [] `shouldBe` Nothing+ it "returns Nothing if the last entity is not an HtmlText" $+ forM_ (["", "foo"] :: [Text]) $ \ suffix -> do+ clipSuffixText suffix+ [ HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ ] `shouldBe` Nothing+ clipSuffixText suffix+ [ HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ , HtmlComment [] "foo"+ ] `shouldBe` Nothing+ clipSuffixText suffix [HtmlEndTag [] P] `shouldBe` Nothing+ clipSuffixText suffix [HtmlCdata [] "foo"] `shouldBe` Nothing+ it "returns Just [] if entities are empty and a suffix is empty too" $+ clipSuffixText "" [] `shouldBe` Just []+ it "returns entities with the suffix text dropped" $ do+ clipSuffixText "bar"+ [ HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ , HtmlText [] "foobar"+ ]+ `shouldBe` Just+ [ HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ , HtmlText [] "foo"+ ]+ clipSuffixText "foo"+ [ HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ , HtmlText [] "foo"+ ]+ `shouldBe` Just+ [ HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ ]+ it "ignores HtmlComment entities but preseves them" $ do+ clipSuffixText "bar"+ [ HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ , HtmlText [] "foobar"+ , HtmlComment [] "comment"+ ]+ `shouldBe` Just+ [ HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ , HtmlText [] "foo"+ , HtmlComment [] "comment"+ ]+ clipSuffixText "foo"+ [ HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ , HtmlText [] "foo"+ , HtmlComment [] "comment"+ ]+ `shouldBe` Just+ [ HtmlStartTag [] P ""+ , HtmlText [P] "foo"+ , HtmlEndTag [] P+ , HtmlComment [] "comment"+ ]++ specify "clipText" $ do+ clipText "foo" "baz"+ [ HtmlText [] "foo"+ , HtmlStartTag [] P ""+ , HtmlText [P] "bar"+ , HtmlEndTag [] P+ , HtmlText [] "baz"+ ] `shouldBe` Just+ [ HtmlStartTag [] P ""+ , HtmlText [P] "bar"+ , HtmlEndTag [] P+ ]+ clipText "foo" "quux"+ [ HtmlText [] "foobar"+ , HtmlStartTag [] P ""+ , HtmlText [P] "baz"+ , HtmlEndTag [] P+ , HtmlText [] "quxquux"+ ] `shouldBe` Just+ [ HtmlText [] "bar"+ , HtmlStartTag [] P ""+ , HtmlText [P] "baz"+ , HtmlEndTag [] P+ , HtmlText [] "qux"+ ]
+ test/Text/Seonbi/Html/PreservationSpec.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+module Text.Seonbi.Html.PreservationSpec (spec) where++import Test.Hspec++import Text.Seonbi.Html.Entity+import Text.Seonbi.Html.Preservation+import Text.Seonbi.Html.Tag++spec :: Spec+spec = do+ specify "isPreservedTag" $ do+ P `shouldNotSatisfy` isPreservedTag+ Em `shouldNotSatisfy` isPreservedTag+ Title `shouldNotSatisfy` isPreservedTag+ Canvas `shouldSatisfy` isPreservedTag+ Code `shouldSatisfy` isPreservedTag+ Kbd `shouldSatisfy` isPreservedTag+ Pre `shouldSatisfy` isPreservedTag+ Script `shouldSatisfy` isPreservedTag+ Style `shouldSatisfy` isPreservedTag+ Template `shouldSatisfy` isPreservedTag+ TextArea `shouldSatisfy` isPreservedTag+ specify "isPreservedTagStack" $ do+ [] `shouldNotSatisfy` isPreservedTagStack+ [P, Em] `shouldNotSatisfy` isPreservedTagStack+ [Html, Head, Title] `shouldNotSatisfy` isPreservedTagStack+ [Div, Script] `shouldSatisfy` isPreservedTagStack+ [Html, Head, Style] `shouldSatisfy` isPreservedTagStack+ [P, Kbd] `shouldSatisfy` isPreservedTagStack+ [Pre, Code] `shouldSatisfy` isPreservedTagStack+ [Template, P] `shouldSatisfy` isPreservedTagStack+ specify "shouldBePreserved" $ do+ HtmlStartTag [] P "" `shouldNotSatisfy` isPreservedEntity+ HtmlEndTag [] P `shouldNotSatisfy` isPreservedEntity+ HtmlText [] "" `shouldNotSatisfy` isPreservedEntity+ HtmlCdata [] "" `shouldNotSatisfy` isPreservedEntity+ HtmlComment [] " ... " `shouldSatisfy` isPreservedEntity+ HtmlStartTag [P] Em "" `shouldNotSatisfy` isPreservedEntity+ HtmlEndTag [P] Em `shouldNotSatisfy` isPreservedEntity+ HtmlText [P] "" `shouldNotSatisfy` isPreservedEntity+ HtmlCdata [P] "" `shouldNotSatisfy` isPreservedEntity+ HtmlComment [P] " ... " `shouldSatisfy` isPreservedEntity+ HtmlStartTag [P] Code "" `shouldSatisfy` isPreservedEntity+ HtmlEndTag [P] Code `shouldSatisfy` isPreservedEntity+ HtmlStartTag [Pre] Span "" `shouldSatisfy` isPreservedEntity+ HtmlEndTag [Pre] Span `shouldSatisfy` isPreservedEntity+ HtmlText [Pre] "" `shouldSatisfy` isPreservedEntity+ HtmlCdata [Pre] "" `shouldSatisfy` isPreservedEntity+ HtmlComment [Pre] " ... " `shouldSatisfy` isPreservedEntity
+ test/Text/Seonbi/Html/PrinterSpec.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+module Text.Seonbi.Html.PrinterSpec (spec) where++import Data.Text.Lazy+import Test.Hspec++import Text.Seonbi.Html.Entity+import Text.Seonbi.Html.Printer+import Text.Seonbi.Html.Tag++sample :: [HtmlEntity]+sample =+ [ HtmlComment { tagStack = [], comment = " foo " }+ , HtmlStartTag { tagStack = [], tag = P, rawAttributes = " id=\"a\"" }+ , HtmlText { tagStack = [P], rawText = "Hello," }+ , HtmlStartTag { tagStack = [P], tag = BR, rawAttributes = "" }+ , HtmlEndTag { tagStack = [P], tag = BR }+ , HtmlText { tagStack = [P], rawText = "\n" }+ , HtmlStartTag { tagStack = [P], tag = Em, rawAttributes = "class=\"b\"" }+ , HtmlCdata { tagStack = [P, Em], text = "world" }+ , HtmlEndTag { tagStack = [P], tag = Em }+ , HtmlText { tagStack = [P], rawText = "!" }+ , HtmlEndTag { tagStack = [], tag = P }+ , HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlEndTag { tagStack = [], tag = P }+ ]++spec :: Spec+spec = do+ specify "printHtml" $+ printHtml sample `shouldBe` Data.Text.Lazy.concat+ [ "<!-- foo --><p id=\"a\">Hello,<br>\n"+ , "<em class=\"b\"><![CDATA[world]]></em>!</p><p></p>"+ ]+ specify "printXhtml" $+ printXhtml sample `shouldBe` Data.Text.Lazy.concat+ [ "<!-- foo --><p id=\"a\">Hello,<br/>\n"+ , "<em class=\"b\"><![CDATA[world]]></em>!</p><p></p>"+ ]
+ test/Text/Seonbi/Html/ScannerSpec.hs view
@@ -0,0 +1,295 @@+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+module Text.Seonbi.Html.ScannerSpec (spec) where++import Test.Hspec++import Text.Seonbi.Html.Entity+import Text.Seonbi.Html.Scanner+import Text.Seonbi.Html.Tag+import Text.Seonbi.Html.TextNormalizer++isDone :: Result a -> Bool+isDone Done {} = True+isDone Fail {} = False++shouldBeDone :: (Eq a, Show a) => Result a -> a -> Expectation+shouldBeDone result expected = do+ result `shouldSatisfy` isDone+ let Done "" r = result+ r `shouldBe` expected++spec :: Spec+spec =+ describe "scanHtml" $ do+ it "returns an empty list if the input is empty" $+ scanHtml "" `shouldBeDone` []++ it "parses text nodes" $+ scanHtml "foobar" `shouldBeDone`+ [HtmlText { tagStack = [], rawText = "foobar" }]++ it "parses HTML comments" $ do+ scanHtml "<!-- foo -->" `shouldBeDone`+ [HtmlComment { tagStack = [], comment = " foo " }]+ scanHtml "<!-- foo- -->" `shouldBeDone`+ [HtmlComment { tagStack = [], comment = " foo- " }]+ scanHtml "<!-- foo-> -->" `shouldBeDone`+ [HtmlComment { tagStack = [], comment = " foo-> " }]+ scanHtml "<!-- foo-- -->" `shouldBeDone`+ [HtmlComment { tagStack = [], comment = " foo-- " }]+ scanHtml "foo <!-- bar -->" `shouldBeDone`+ [ HtmlText { tagStack = [], rawText = "foo " }+ , HtmlComment { tagStack = [], comment = " bar " }+ ]+ scanHtml "<!-- foo --> bar" `shouldBeDone`+ [ HtmlComment { tagStack = [], comment = " foo " }+ , HtmlText { tagStack = [], rawText = " bar" }+ ]+ scanHtml "foo <!-- bar --> baz" `shouldBeDone`+ [ HtmlText { tagStack = [], rawText = "foo " }+ , HtmlComment { tagStack = [], comment = " bar " }+ , HtmlText { tagStack = [], rawText = " baz" }+ ]+ scanHtml "<p>foo <!-- bar baz --> qux</p>" `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText { tagStack = [P], rawText = "foo " }+ , HtmlComment { tagStack = [P], comment = " bar baz " }+ , HtmlText { tagStack = [P], rawText = " qux" }+ , HtmlEndTag { tagStack = [], tag = P }+ ]+ scanHtml "<p>foo <!-- <b>bar</b> baz --> qux</p>" `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText { tagStack = [P], rawText = "foo " }+ , HtmlComment { tagStack = [P], comment = " <b>bar</b> baz " }+ , HtmlText { tagStack = [P], rawText = " qux" }+ , HtmlEndTag { tagStack = [], tag = P }+ ]++ it "parses CDATA sections" $ do+ scanHtml "<![CDATA[foo]]>" `shouldBeDone`+ [HtmlCdata { tagStack = [], text = "foo" }]+ scanHtml "foo <![CDATA[bar]]>" `shouldBeDone`+ [ HtmlText { tagStack = [], rawText = "foo " }+ , HtmlCdata { tagStack = [], text = "bar" }+ ]+ scanHtml "<![CDATA[foo]]> bar" `shouldBeDone`+ [ HtmlCdata { tagStack = [], text = "foo" }+ , HtmlText { tagStack = [], rawText = " bar" }+ ]+ scanHtml "foo <![CDATA[bar]]> baz" `shouldBeDone`+ [ HtmlText { tagStack = [], rawText = "foo " }+ , HtmlCdata { tagStack = [], text = "bar" }+ , HtmlText { tagStack = [], rawText = " baz" }+ ]+ scanHtml "<![CDATA[foo] ]]>" `shouldBeDone`+ [HtmlCdata { tagStack = [], text = "foo] " }]+ scanHtml "<p>foo <![CDATA[bar baz]]> qux</p>" `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText { tagStack = [P], rawText = "foo " }+ , HtmlCdata { tagStack = [P], text = "bar baz" }+ , HtmlText { tagStack = [P], rawText = " qux" }+ , HtmlEndTag { tagStack = [], tag = P }+ ]+ scanHtml "<p>foo <![CDATA[<b>bar</b> baz]]> qux</p>" `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText { tagStack = [P], rawText = "foo " }+ , HtmlCdata { tagStack = [P], text = "<b>bar</b> baz" }+ , HtmlText { tagStack = [P], rawText = " qux" }+ , HtmlEndTag { tagStack = [], tag = P }+ ]++ it "treats malformed CDATA sections as text nodes" $+ (normalizeText <$> scanHtml "<![CDATA[foo") `shouldBeDone`+ [HtmlText { tagStack = [], rawText = "<![CDATA[foo" }]++ it "parses html start tags" $ do+ scanHtml "<p>" `shouldBeDone`+ [HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }]+ scanHtml "<p><em>" `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlStartTag { tagStack = [P], tag = Em, rawAttributes = "" }+ ]++ it "parses HTML start tags having attributes" $ do+ scanHtml "<p class=foo>" `shouldBeDone`+ [ HtmlStartTag+ { tagStack = []+ , tag = P+ , rawAttributes = " class=foo"+ }+ ]+ scanHtml "<a href=\"https://example.com/\">" `shouldBeDone`+ [ HtmlStartTag+ { tagStack = []+ , tag = A+ , rawAttributes = " href=\"https://example.com/\""+ }+ ]++ it "parses html end tags" $ do+ scanHtml "<p></p>" `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlEndTag { tagStack = [], tag = P }+ ]+ scanHtml "<p><em>test</em></p>" `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlStartTag { tagStack = [P], tag = Em, rawAttributes = "" }+ , HtmlText { tagStack = [P, Em], rawText = "test" }+ , HtmlEndTag { tagStack = [P], tag = Em }+ , HtmlEndTag { tagStack = [], tag = P }+ ]++ it "can parse even if tags end in wrong order" $ do+ scanHtml "<p><em>test</p></em>" `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlStartTag { tagStack = [P], tag = Em, rawAttributes = "" }+ , HtmlText { tagStack = [P, Em], rawText = "test" }+ , HtmlEndTag { tagStack = [Em], tag = P }+ , HtmlEndTag { tagStack = [], tag = Em }+ ]+ scanHtml "<p><b class=\"baz\">Hel<i>lo Wo</b>rld</i></p>"+ `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlStartTag+ { tagStack = [P]+ , tag = B+ , rawAttributes = " class=\"baz\""+ }+ , HtmlText { tagStack = [P, B], rawText = "Hel" }+ , HtmlStartTag+ { tagStack = [P, B]+ , tag = I+ , rawAttributes = ""+ }+ , HtmlText { tagStack = [P, B, I], rawText = "lo Wo" }+ , HtmlEndTag { tagStack = [P, I], tag = B }+ , HtmlText { tagStack = [P, I], rawText = "rld" }+ , HtmlEndTag { tagStack = [P], tag = I }+ , HtmlEndTag { tagStack = [], tag = P }+ ]++ it "can parse XHTML-style self-closing tags" $+ scanHtml "<p><em/>" `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlStartTag { tagStack = [P], tag = Em, rawAttributes = "" }+ , HtmlEndTag { tagStack = [P], tag = Em }+ ]++ it "emits both start and end tags for void tags (e.g., <hr>)" $ do+ scanHtml "<p><hr>" `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlStartTag { tagStack = [P], tag = HR, rawAttributes = "" }+ , HtmlEndTag { tagStack = [P], tag = HR }+ ]+ scanHtml+ "<div><p>foo</p><hr><p>bar <img src=\"a.jpg\"></p><hr></div>"+ `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = Div, rawAttributes = "" }+ , HtmlStartTag { tagStack = [Div], tag = P, rawAttributes = "" }+ , HtmlText { tagStack = [Div, P], rawText = "foo" }+ , HtmlEndTag { tagStack = [Div], tag = P }+ , HtmlStartTag+ { tagStack = [Div]+ , tag = HR+ , rawAttributes = ""+ }+ , HtmlEndTag { tagStack = [Div], tag = HR }+ , HtmlStartTag { tagStack = [Div], tag = P, rawAttributes = "" }+ , HtmlText { tagStack = [Div, P], rawText = "bar " }+ , HtmlStartTag+ { tagStack = [Div, P]+ , tag = Img+ , rawAttributes = " src=\"a.jpg\""+ }+ , HtmlEndTag { tagStack = [Div, P], tag = Img }+ , HtmlEndTag { tagStack = [Div], tag = P }+ , HtmlStartTag+ { tagStack = [Div]+ , tag = HR+ , rawAttributes = ""+ }+ , HtmlEndTag { tagStack = [Div], tag = HR }+ , HtmlEndTag { tagStack = [], tag = Div }+ ]+ scanHtml "<embed></embed>" `shouldBeDone`+ [ HtmlStartTag+ { tagStack = []+ , tag = Embed+ , rawAttributes = ""+ }+ , HtmlEndTag { tagStack = [], tag = Embed }+ ]++ it "can parses a flat element" $+ scanHtml "<div>Hello</div>" `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = Div, rawAttributes = "" }+ , HtmlText { tagStack = [Div], rawText = "Hello" }+ , HtmlEndTag { tagStack = [], tag = Div }+ ]++ it "can parses nested elements" $ do+ scanHtml "<div><p class=foo>Hello</p><p class='bar'>World</p></div>"+ `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = Div, rawAttributes = "" }+ , HtmlStartTag+ { tagStack = [Div]+ , tag = P+ , rawAttributes = " class=foo"+ }+ , HtmlText { tagStack = [Div, P], rawText = "Hello" }+ , HtmlEndTag { tagStack = [Div], tag = P }+ , HtmlStartTag+ { tagStack = [Div]+ , tag = P+ , rawAttributes = " class='bar'"+ }+ , HtmlText { tagStack = [Div, P], rawText = "World" }+ , HtmlEndTag { tagStack = [Div], tag = P }+ , HtmlEndTag { tagStack = [], tag = Div }+ ]+ scanHtml "<p><b class=\"baz\">Hel<i>lo Wo</i>rld</b></p>"+ `shouldBeDone`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlStartTag+ { tagStack = [P]+ , tag = B+ , rawAttributes = " class=\"baz\""+ }+ , HtmlText { tagStack = [P, B], rawText = "Hel" }+ , HtmlStartTag+ { tagStack = [P, B]+ , tag = I+ , rawAttributes = ""+ }+ , HtmlText { tagStack = [P, B, I], rawText = "lo Wo" }+ , HtmlEndTag { tagStack = [P, B], tag = I }+ , HtmlText { tagStack = [P, B], rawText = "rld" }+ , HtmlEndTag { tagStack = [P], tag = B }+ , HtmlEndTag { tagStack = [], tag = P }+ ]++ it "can parses an HTML fragment having multiple root elements" $+ scanHtml+ "<p\nid=\"a\">Hello <b>world</b>!</p>\n<p>Second paragraph.</p>"+ `shouldBeDone`+ [ HtmlStartTag+ { tagStack = []+ , tag = P+ , rawAttributes = "\nid=\"a\""+ }+ , HtmlText { tagStack = [P], rawText = "Hello " }+ , HtmlStartTag { tagStack = [P], tag = B, rawAttributes = "" }+ , HtmlText { tagStack = [P, B], rawText = "world" }+ , HtmlEndTag { tagStack = [P], tag = B }+ , HtmlText { tagStack = [P], rawText = "!" }+ , HtmlEndTag { tagStack = [], tag = P }+ , HtmlText { tagStack = [], rawText = "\n" }+ , HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText { tagStack = [P], rawText = "Second paragraph." }+ , HtmlEndTag { tagStack = [], tag = P }+ ]++ it "treats an invalid tag as a text node" $+ (normalizeText <$> scanHtml "<invalid>") `shouldBeDone`+ [HtmlText { tagStack = [], rawText = "<invalid>" }]
+ test/Text/Seonbi/Html/TextNormalizerSpec.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+module Text.Seonbi.Html.TextNormalizerSpec (spec) where++import Control.Monad++import Test.Hspec++import Text.Seonbi.Html.Entity+import Text.Seonbi.Html.Tag+import Text.Seonbi.Html.TagStack+import Text.Seonbi.Html.TextNormalizer++spec :: Spec+spec = do+ specify "normalizeText" $+ normalizeText+ [ HtmlText { tagStack = [], rawText = "foo " }+ , HtmlText { tagStack = [], rawText = "& bar" }+ , HtmlCdata { tagStack = [], text = " & baz" }+ , HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText { tagStack = [P], rawText = "qux " }+ , HtmlCdata { tagStack = [P], text = "& \"quux\"" }+ , HtmlEndTag { tagStack = [], tag = P }+ , HtmlCdata { tagStack = [], text = "<end>" }+ ] `shouldBe`+ [ HtmlText { tagStack = [], rawText = "foo & bar & baz" }+ , HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText+ { tagStack = [P]+ , rawText = "qux & "quux""+ }+ , HtmlEndTag { tagStack = [], tag = P }+ , HtmlText { tagStack = [], rawText = "<end>" }+ ]++ describe "normalizeCdata" $ do+ let s1 = [] :: HtmlTagStack+ let s2 = [Div, P] :: HtmlTagStack+ specify "HtmlStartTag" $ do+ let entity1 = HtmlStartTag+ { tagStack = s1+ , tag = P+ , rawAttributes = ""+ }+ normalizeCdata entity1 `shouldBe` entity1+ let entity2 = HtmlStartTag+ { tagStack = s2+ , tag = P+ , rawAttributes = " class=\"entity2\""+ }+ normalizeCdata entity2 `shouldBe` entity2+ let stacks = [s1, s2] :: [HtmlTagStack]+ forM_ stacks $ \ s -> do+ specify ("HtmlEndTag: " ++ show s) $ do+ let e = HtmlEndTag { tagStack = s, tag = P }+ normalizeCdata e `shouldBe` e+ specify ("HtmlText: " ++ show s) $ do+ let e = HtmlText { tagStack = s, rawText = "foo & bar" }+ normalizeCdata e `shouldBe` e+ specify ("HtmlComment: " ++ show s) $ do+ let e = HtmlComment { tagStack = s, comment = "foo" }+ normalizeCdata e `shouldBe` e+ specify ("HtmlCdata: " ++ show s) $ do+ let e = HtmlCdata { tagStack = s, text = "<p>foo & bar</p>" }+ normalizeCdata e `shouldBe`+ HtmlText+ { tagStack = s+ , rawText = "<p>foo & bar</p>"+ }++ specify "escapeHtmlEntities" $ do+ escapeHtmlEntities "<p id=\"foo\">" `shouldBe`+ "<p id="foo">"+ escapeHtmlEntities "AT&T" `shouldBe`+ "AT&T"
+ test/Text/Seonbi/Html/WrapperSpec.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+module Text.Seonbi.Html.WrapperSpec (spec) where++import Test.Hspec++import Text.Seonbi.Html.Entity+import Text.Seonbi.Html.Tag+import Text.Seonbi.Html.Wrapper++spec :: Spec+spec =+ specify "wrap" $+ wrap [Div, Article] BlockQuote " class=\"q\""+ [ HtmlStartTag+ { tagStack = [Div, Article]+ , tag = P+ , rawAttributes = ""+ }+ , HtmlText { tagStack = [Div, Article, P], rawText = "foo" }+ , HtmlStartTag+ { tagStack = [Div, Article, P]+ , tag = Em+ , rawAttributes = ""+ }+ , HtmlCdata { tagStack = [Div, Article, P, Em], text = "bar" }+ , HtmlEndTag { tagStack = [Div, Article, P], tag = Em }+ , HtmlComment { tagStack = [Div, Article, P], comment = " baz " }+ , HtmlEndTag { tagStack = [Div, Article], tag = P }+ ] `shouldBe`+ [ HtmlStartTag+ { tagStack = [Div, Article]+ , tag = BlockQuote+ , rawAttributes = " class=\"q\""+ }+ , HtmlStartTag+ { tagStack = [Div, Article, BlockQuote]+ , tag = P+ , rawAttributes = ""+ }+ , HtmlText+ { tagStack = [Div, Article, BlockQuote, P]+ , rawText = "foo"+ }+ , HtmlStartTag+ { tagStack = [Div, Article, BlockQuote, P]+ , tag = Em+ , rawAttributes = ""+ }+ , HtmlCdata+ { tagStack = [Div, Article, BlockQuote, P, Em]+ , text = "bar"+ }+ , HtmlEndTag { tagStack = [Div, Article, BlockQuote, P], tag = Em }+ , HtmlComment+ { tagStack = [Div, Article, BlockQuote, P]+ , comment = " baz "+ }+ , HtmlEndTag { tagStack = [Div, Article, BlockQuote], tag = P }+ , HtmlEndTag { tagStack = [Div, Article], tag = BlockQuote }+ ]
+ test/Text/Seonbi/PunctuationSpec.hs view
@@ -0,0 +1,456 @@+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+module Text.Seonbi.PunctuationSpec (spec) where++import Control.Monad+import Data.Maybe++import Data.Set+import Data.Text+import Test.Hspec++import Text.Seonbi.Html+import Text.Seonbi.Punctuation++arrowSample :: HtmlTag -> [HtmlEntity]+arrowSample tag' =+ [ HtmlStartTag { tagStack = [], tag = tag', rawAttributes = "" }+ , HtmlText+ { tagStack = [tag']+ , rawText = "A -> B, B <- A, C <-> D"+ }+ , HtmlStartTag { tagStack = [tag'], tag = BR, rawAttributes = "" }+ , HtmlEndTag { tagStack = [tag'], tag = BR }+ , HtmlText+ { tagStack = [tag']+ , rawText = "a => b, b <= a, c <=> d"+ }+ , HtmlEndTag { tagStack = [], tag = tag' }+ ]++ellipsisSample :: Text -> Text -> [HtmlEntity]+ellipsisSample periods periods' =+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText+ { tagStack = [P]+ , rawText = Data.Text.concat+ [ "These periods"+ , periods+ , " should be an ellipsis."+ ]+ }+ , HtmlEndTag { tagStack = [], tag = P }+ , HtmlStartTag { tagStack = [], tag = Pre, rawAttributes = "" }+ , HtmlText+ { tagStack = [Pre]+ , rawText = "This should be ignored" `Data.Text.append` periods'+ }+ , HtmlEndTag { tagStack = [], tag = Pre }+ ]++titleInputSample :: [HtmlEntity]+titleInputSample =+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText { tagStack = [P], rawText = "<<無情" }+ , HtmlText { tagStack = [P], rawText = ">>, <<흙>" }+ , HtmlText { tagStack = [P], rawText = "> 等을 쓴 " }+ , HtmlText { tagStack = [P], rawText = "李光洙의 日本 이름은 " }+ , HtmlText { tagStack = [P], rawText = "香山光郞다." }+ , HtmlEndTag { tagStack = [], tag = P }+ ]++titleOutputSample :: Text -> Text -> Bool -> [HtmlEntity]+titleOutputSample start end citeTag = catMaybes+ [ Just HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , Just HtmlText { tagStack = [P], rawText = start }+ , cite HtmlStartTag { tagStack = [P], tag = Cite , rawAttributes = "" }+ , Just HtmlText { tagStack = titleStack, rawText = "無情" }+ , cite HtmlEndTag { tagStack = [P], tag = Cite }+ , Just HtmlText { tagStack = [P], rawText = end }+ , Just HtmlText { tagStack = [P], rawText = ", " }+ , Just HtmlText { tagStack = [P], rawText = start }+ , cite HtmlStartTag { tagStack = [P], tag = Cite , rawAttributes = "" }+ , Just HtmlText { tagStack = titleStack, rawText = "흙" }+ , cite HtmlEndTag { tagStack = [P], tag = Cite }+ , Just HtmlText { tagStack = [P], rawText = end }+ , Just HtmlText+ { tagStack = [P]+ , rawText = " 等을 쓴 李光洙의 日本 이름은 香山光郞다."+ }+ , Just HtmlEndTag { tagStack = [], tag = P }+ ]+ where+ titleStack :: HtmlTagStack+ titleStack = if citeTag then [P, Cite] else [P]+ cite :: HtmlEntity -> Maybe HtmlEntity+ cite = if citeTag then Just else const Nothing++transformQuote' :: Quotes -> [HtmlEntity] -> [HtmlEntity]+transformQuote' settings = normalizeText . transformQuote settings++quoteInputSample :: [HtmlEntity]+quoteInputSample =+ [ HtmlStartTag { tagStack = [], tag = H1, rawAttributes = "" }+ , HtmlText { tagStack = [H1], rawText = "太陽의風俗" }+ , HtmlEndTag { tagStack = [], tag = H1 }+ , HtmlStartTag { tagStack = [], tag = H2, rawAttributes = "" }+ , HtmlText { tagStack = [H2], rawText = "어떤親한"詩의벗"에게" }+ , HtmlEndTag { tagStack = [], tag = H2 }+ , HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText { tagStack = [P], rawText = "(前略) " }+ , HtmlCdata+ { tagStack = [P]+ , text = "嘆息. 그것은 紳士와淑女들의 午後의禮儀가아니고 무엇이냐? "+ }+ , HtmlText+ { tagStack = [P]+ , rawText = Data.Text.concat+ [ "秘密. 어쩌면 그렇게도 粉바른할머니인 十九世紀的 "+ , "'비ー너쓰'냐? "+ ]+ }+ , HtmlCdata+ { tagStack = [P]+ , text = "너는 그것들에게서 지금도 곰팽이냄새를 맡지못하느냐?"+ }+ , HtmlText { tagStack = [P], rawText = " (後略)" }+ , HtmlEndTag { tagStack = [], tag = P }+ ]++quoteOutputSample :: [HtmlEntity] -> [HtmlEntity] -> [HtmlEntity]+quoteOutputSample singleQuoted doubleQuoted = normalizeText $+ [ HtmlStartTag { tagStack = [], tag = H1, rawAttributes = "" }+ , HtmlText { tagStack = [H1], rawText = "太陽의風俗" }+ , HtmlEndTag { tagStack = [], tag = H1 }+ , HtmlStartTag { tagStack = [], tag = H2, rawAttributes = "" }+ , HtmlText { tagStack = [H2], rawText = "어떤親한" }+ ] ++ doubleQuoted +++ [ HtmlText { tagStack = [H2], rawText = "에게" }+ , HtmlEndTag { tagStack = [], tag = H2 }+ , HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText+ { tagStack = [P]+ , rawText = Data.Text.concat+ [ "(前略) 嘆息. 그것은 紳士와淑女들의 午後의禮儀가아니고 무엇이냐? "+ , "秘密. 어쩌면 그렇게도 粉바른할머니인 十九世紀的 "+ ]+ }+ ] ++ singleQuoted +++ [ HtmlText+ { tagStack = [P]+ , rawText =+ "냐? 너는 그것들에게서 지금도 곰팽이냄새를 맡지못하느냐? (後略)"+ }+ , HtmlEndTag { tagStack = [], tag = P }+ ]++ignoredTags :: [HtmlTag]+ignoredTags = [Code, Kbd, Pre, Script, Style, TextArea]++spec :: Spec+spec = do+ describe "quoteCitation" $ do+ let angleQuotesNoCite = angleQuotes { htmlElement = Nothing }+ cornerBracketsNoCite = cornerBrackets { htmlElement = Nothing }+ specify "angleQuotes w/ citeTag" $+ quoteCitation angleQuotes titleInputSample `shouldBe`+ titleOutputSample "《" "》" True+ specify "angleQuotes w/o citeTag" $+ quoteCitation angleQuotesNoCite titleInputSample+ `shouldBe` titleOutputSample "《" "》" False+ specify "cornerBrackets w/ citeTag" $+ quoteCitation cornerBrackets titleInputSample `shouldBe`+ titleOutputSample "『" "』" True+ specify "cornerBrackets w/o citeTag" $+ quoteCitation cornerBracketsNoCite titleInputSample `shouldBe`+ titleOutputSample "『" "』" False+ it "is idempotent" $ do+ let f = quoteCitation angleQuotes+ normalizeText (f (f titleInputSample)) `shouldBe`+ normalizeText (quoteCitation angleQuotes titleInputSample)+ forM_ ignoredTags $ \ tag' ->+ it ("ignores <" ++ unpack (htmlTagName tag') ++ "> tags") $+ (normalizeText . quoteCitation angleQuotes)+ [ HtmlStartTag+ { tagStack = []+ , tag = Div+ , rawAttributes = ""+ }+ , HtmlStartTag+ { tagStack = [Div]+ , tag = P+ , rawAttributes = ""+ }+ , HtmlText+ { tagStack = [Div, P]+ , rawText = "이 안의 <타이틀>은 바뀐다."+ }+ , HtmlEndTag { tagStack = [Div], tag = P }+ , HtmlStartTag+ { tagStack = [Div]+ , tag = tag'+ , rawAttributes = ""+ }+ , HtmlText+ { tagStack = [Div, tag']+ , rawText = "this is not a<title> but_code"+ }+ , HtmlEndTag { tagStack = [Div], tag = tag' }+ , HtmlEndTag { tagStack = [], tag = Div }+ ]+ `shouldBe`+ [ HtmlStartTag+ { tagStack = []+ , tag = Div+ , rawAttributes = ""+ }+ , HtmlStartTag+ { tagStack = [Div]+ , tag = P+ , rawAttributes = ""+ }+ , HtmlText+ { tagStack = [Div, P]+ , rawText = "이 안의 〈"+ }+ , HtmlStartTag+ { tagStack = [Div, P]+ , tag = Cite+ , rawAttributes = ""+ }+ , HtmlText { tagStack = [Div, P, Cite], rawText = "타이틀" }+ , HtmlEndTag { tagStack = [Div, P], tag = Cite }+ , HtmlText+ { tagStack = [Div, P]+ , rawText = "〉은 바뀐다."+ }+ , HtmlEndTag { tagStack = [Div], tag = P }+ , HtmlStartTag+ { tagStack = [Div]+ , tag = tag'+ , rawAttributes = ""+ }+ , HtmlText+ { tagStack = [Div, tag']+ , rawText = "this is not a<title> but_code"+ }+ , HtmlEndTag { tagStack = [Div], tag = tag' }+ , HtmlEndTag { tagStack = [], tag = Div }+ ]++ describe "transformArrow" $ do+ specify "[]" $+ transformArrow [] (arrowSample P) `shouldBe`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText+ { tagStack = [P]+ , rawText = "A → B, B ← A, C ←> D"+ }+ , HtmlStartTag { tagStack = [P], tag = BR, rawAttributes = "" }+ , HtmlEndTag { tagStack = [P], tag = BR }+ , HtmlText+ { tagStack = [P]+ , rawText = "a => b, b <= a, c <=> d"+ }+ , HtmlEndTag { tagStack = [], tag = P }+ ]+ specify "[LeftRight]" $+ transformArrow [LeftRight] (arrowSample P) `shouldBe`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText+ { tagStack = [P]+ , rawText = "A → B, B ← A, C ↔ D"+ }+ , HtmlStartTag { tagStack = [P], tag = BR, rawAttributes = "" }+ , HtmlEndTag { tagStack = [P], tag = BR }+ , HtmlText+ { tagStack = [P]+ , rawText = "a => b, b <= a, c <=> d"+ }+ , HtmlEndTag { tagStack = [], tag = P }+ ]+ specify "[DoubleArrow]" $+ transformArrow [DoubleArrow] (arrowSample P) `shouldBe`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText+ { tagStack = [P]+ , rawText = "A → B, B ← A, C ←> D"+ }+ , HtmlStartTag { tagStack = [P], tag = BR, rawAttributes = "" }+ , HtmlEndTag { tagStack = [P], tag = BR }+ , HtmlText+ { tagStack = [P]+ , rawText = "a ⇒ b, b ⇐ a, c ⇐> d"+ }+ , HtmlEndTag { tagStack = [], tag = P }+ ]+ specify "[LeftRight, DoubleArrow]" $+ transformArrow [LeftRight, DoubleArrow] (arrowSample P) `shouldBe`+ [ HtmlStartTag { tagStack = [], tag = P, rawAttributes = "" }+ , HtmlText+ { tagStack = [P]+ , rawText = "A → B, B ← A, C ↔ D"+ }+ , HtmlStartTag { tagStack = [P], tag = BR, rawAttributes = "" }+ , HtmlEndTag { tagStack = [P], tag = BR }+ , HtmlText+ { tagStack = [P]+ , rawText = "a ⇒ b, b ⇐ a, c ⇔ d"+ }+ , HtmlEndTag { tagStack = [], tag = P }+ ]+ forM_ ignoredTags $ \ tag' ->+ it ("ignores <" ++ unpack (htmlTagName tag') ++ "> tags") $ do+ let optionsSet =+ [ []+ , [LeftRight]+ , [DoubleArrow]+ , [LeftRight, DoubleArrow]+ ] :: [Set ArrowTransformationOption]+ forM_ optionsSet $ \ options ->+ let+ entities = transformArrow options (arrowSample tag')+ in+ entities `shouldBe` entities++ specify "transformEllipsis" $ do+ let sample x = ellipsisSample x x+ transformEllipsis (sample "...") `shouldBe`+ ellipsisSample "…" "..."+ transformEllipsis (sample "...") `shouldBe`+ ellipsisSample "…" "..."++ describe "transformQuote" $ do+ it "transforms apostrophes and straight quotes into typographic ones" $+ transformQuote' curvedQuotes quoteInputSample `shouldBe`+ quoteOutputSample+ [ HtmlText+ { tagStack = [P]+ , rawText = "‘비ー너쓰’"+ }+ ]+ [ HtmlText+ { tagStack = [H2]+ , rawText = "“詩의벗”"+ }+ ]+ it "transforms apostrophes and straight quotes into guillements" $+ transformQuote' guillemets quoteInputSample `shouldBe`+ quoteOutputSample+ [ HtmlText+ { tagStack = [P]+ , rawText = "〈비ー너쓰〉"+ }+ ]+ [ HtmlText+ { tagStack = [H2]+ , rawText = "《詩의벗》"+ }+ ]+ it "transforms straight quotes into <q> elements" $+ transformQuote' curvedSingleQuotesWithQ quoteInputSample `shouldBe`+ quoteOutputSample+ [ HtmlText+ { tagStack = [P]+ , rawText = "‘비ー너쓰’"+ }+ ]+ [ HtmlStartTag+ { tagStack = [H2]+ , tag = Q+ , rawAttributes = ""+ }+ , HtmlText { tagStack = [H2, Q], rawText = "詩의벗" }+ , HtmlEndTag { tagStack = [H2], tag = Q }+ ]+ it "transforms nested quotes" $ do+ let input =+ [ HtmlStartTag [] P ""+ , HtmlCdata [P] "A \"nest"+ , HtmlStartTag [P] Em ""+ , HtmlCdata [P, Em] "ed"+ , HtmlEndTag [P] Em+ , HtmlCdata [P] " 'quote' "+ , HtmlText [P] "sentence" here."+ , HtmlEndTag [] P+ ]+ transformQuote' curvedQuotes input `shouldBe`+ [ HtmlStartTag [] P ""+ , HtmlText [P] "A “nest"+ , HtmlStartTag [P] Em ""+ , HtmlText [P, Em] "ed"+ , HtmlEndTag [P] Em+ , HtmlText+ [P]+ " ‘quote’ sentence” here."+ , HtmlEndTag [] P+ ]+ transformQuote' curvedSingleQuotesWithQ input `shouldBe`+ [ HtmlStartTag [] P ""+ , HtmlText [P] "A "+ , HtmlStartTag [P] Q ""+ , HtmlText [P, Q] "nest"+ , HtmlStartTag [P, Q] Em ""+ , HtmlText [P, Q, Em] "ed"+ , HtmlEndTag [P, Q] Em+ , HtmlText [P, Q] " ‘quote’ sentence"+ , HtmlEndTag [P] Q+ , HtmlText [P] " here."+ , HtmlEndTag [] P+ ]+ transformQuote' curvedQuotes [HtmlText [] ""'“‘ "] `shouldBe`+ [HtmlText [] ""'“‘ "]+ forM_ ignoredTags $ \ tag' -> do+ let tagStr = '<' : unpack (htmlTagName tag') ++ ">"+ it ("does not transform anything within " ++ tagStr ++ " tags") $ do+ let input =+ [ HtmlStartTag [] tag' ""+ , HtmlText+ { tagStack = [tag']+ , rawText = Data.Text.append+ "It should not be changed: "+ ""unchanged"."+ }+ , HtmlEndTag [] tag'+ ]+ transformQuote' curvedQuotes input `shouldBe` input+ transformQuote' guillemets input `shouldBe` input+ transformQuote' curvedSingleQuotesWithQ input `shouldBe` input++ describe "transformEmDash" $ do+ it "transforms a single hyphen surrounded by spaces into an em dash" $+ transformEmDash+ [ HtmlStartTag [] P ""+ , HtmlText [P]+ "A hyphen - U+002D HYPHEN-MINUS - to em dash."+ , HtmlEndTag [] P+ ] `shouldBe`+ [ HtmlStartTag [] P ""+ , HtmlText [P]+ "A hyphen—U+002D HYPHEN-MINUS—to em dash."+ , HtmlEndTag [] P+ ]+ it "transforms two/three consecutive hyphens into an em dash" $+ transformEmDash+ [ HtmlStartTag [] P ""+ , HtmlText [P]+ "A hyphen--U+002D HYPHEN-MINUS--to em dash."+ , HtmlEndTag [] P+ ] `shouldBe`+ [ HtmlStartTag [] P ""+ , HtmlText [P]+ "A hyphen—U+002D HYPHEN-MINUS—to em dash."+ , HtmlEndTag [] P+ ]+ it "transforms a hangul vowel 'eu' surrounded by spaces to an em dash" $+ transformEmDash+ [ HtmlStartTag [] P ""+ , HtmlText [P]+ "한글 모음 ㅡ U+3161 HANGUL LETTER EU ㅡ 을 줄표로"+ , HtmlEndTag [] P+ ] `shouldBe`+ [ HtmlStartTag [] P ""+ , HtmlText [P]+ "한글 모음—U+3161 HANGUL LETTER EU—을 줄표로"+ , HtmlEndTag [] P+ ]
+ test/Text/Seonbi/Unihan/KHangulSpec.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+module Text.Seonbi.Unihan.KHangulSpec (spec) where++import Data.Either++import Data.Aeson+import Data.Map.Strict+import Test.Hspec++import Text.Seonbi.Unihan.KHangul++spec :: Spec+spec = do+ describe "kHangulData'" $+ it "should be loaded" $+ kHangulData' `shouldSatisfy` isRight+ describe "kHangulData" $+ it "contains Hanja Hangul readings" $+ Data.Map.Strict.lookup '識' kHangulData `shouldBe` Just+ [ ('식', HanjaReadingCitation KS_X_1001 [Education])+ , ('지', HanjaReadingCitation KS_X_1001 [PersonalName])+ ]+ describe "HanjaReadingCitation" $+ specify "parseJSON" $ do+ decode "\"\"" `shouldBe` Just (HanjaReadingCitation NonStandard [])+ decode "\"E\"" `shouldBe` Just+ (HanjaReadingCitation NonStandard [Education])+ decode "\"N\"" `shouldBe` Just+ (HanjaReadingCitation NonStandard [PersonalName])+ decode "\"EN\"" `shouldBe` Just+ (HanjaReadingCitation NonStandard [Education, PersonalName])+ decode "\"0\"" `shouldBe` Just (HanjaReadingCitation KS_X_1001 [])+ decode "\"1\"" `shouldBe` Just (HanjaReadingCitation KS_X_1002 [])+ decode "\"0E\"" `shouldBe` Just+ (HanjaReadingCitation KS_X_1001 [Education])+ decode "\"1N\"" `shouldBe` Just+ (HanjaReadingCitation KS_X_1002 [PersonalName])+ decode "\"2\"" `shouldBe` (Nothing :: Maybe HanjaReadingCitation)+ decode "\"00\"" `shouldBe` (Nothing :: Maybe HanjaReadingCitation)+ decode "\"0Z\"" `shouldBe` (Nothing :: Maybe HanjaReadingCitation)+ decode "0" `shouldBe` (Nothing :: Maybe HanjaReadingCitation)+ decode "null" `shouldBe` (Nothing :: Maybe HanjaReadingCitation)
+ test/doctest.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF doctest-discover -optF test/doctest.json #-}
+ test/hlint.hs view
@@ -0,0 +1,12 @@+import Language.Haskell.HLint (hlint)+import System.Exit (exitFailure, exitSuccess)++arguments :: [String]+arguments = ["app", "src", "test"]++main :: IO ()+main = do+ hlints <- hlint arguments+ case hlints of+ [] -> exitSuccess+ _ -> exitFailure