jekyll-epub 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,242 @@
1
+ require 'rubygems'
2
+ require 'jekyll'
3
+ require 'uuid'
4
+ require 'mime/types'
5
+ require 'jekyll/tags/epub'
6
+
7
+ module Jekyll
8
+ class StaticFile #:nodoc:
9
+ # This is a Jekyll[http://jekyllrb.com] extension
10
+ #
11
+ # Give the URL of a static file
12
+ def url #:nodoc:
13
+ File.join( @dir, @name )
14
+ end
15
+ end
16
+
17
+ class Site #:nodoc:
18
+ def all
19
+ if self.config["epub"]["pages-order"]
20
+ pages + posts
21
+ else
22
+ posts + pages
23
+ end
24
+ end
25
+
26
+ # This is a Jekyll[http://jekyllrb.com] extension
27
+ #
28
+ # Same as Site::process but generate the epub.
29
+ def epub #:nodoc:
30
+ self.reset
31
+ self.read
32
+
33
+ # Change layout to use epub
34
+ self.layouts.each do |name, layout|
35
+ self.layouts[name].data['layout'] = layout.data['epub'] if layout.data['epub']
36
+ end
37
+
38
+ # Generate specifics epub files
39
+ FileUtils.rm_rf( self.dest )
40
+ self.package_epub
41
+
42
+ self.render
43
+
44
+ # Apply filters
45
+ self.apply_epub_filters( pages )
46
+ self.apply_epub_filters( posts )
47
+
48
+ self.write
49
+
50
+ # Create epub file
51
+ self.zip
52
+ end
53
+
54
+ # This is a Jekyll[http://jekyllrb.com] extension
55
+ #
56
+ # Generate the specifics epub files : content.opf, toc.ncx, mimetype,
57
+ # page-template.xpgt and META-INF/container.xml
58
+ def package_epub #:nodoc:
59
+ files = []
60
+ order = 0
61
+
62
+ # Check for cover image
63
+ if self.config["epub"]["cover-image"]
64
+ self.config["epub"]["cover"] = {
65
+ "image" => self.config["epub"]["cover-image"],
66
+ "mime" => MIME::Types.type_for( self.config["epub"]["cover-image"] ).to_s
67
+ }
68
+ end
69
+
70
+ (all + static_files).each do |p|
71
+ url = p.url.gsub( /^\//, "" )
72
+ next if url == self.config["epub"]["cover-image"]
73
+ mime = MIME::Types.type_for( url ).to_s
74
+ mime = "application/xhtml+xml" if mime == "text/html"
75
+ next if self.config['exclude'].include?(File.basename( url ))
76
+
77
+ if mime == "" then
78
+ $stderr.puts "** Ignore file #{url}, unknown mime type!"
79
+ next
80
+ end
81
+
82
+ file_data = {
83
+ 'id' => url.gsub( /\/|\./, "_" ),
84
+ 'url' => url,
85
+ 'mime' => mime
86
+ }
87
+ begin
88
+ p.data['layout'] = p.data['epub'] if p.data['epub']
89
+ file_data['title'] = p.data["title"]
90
+ file_data['order'] = order
91
+ order += 1
92
+ rescue => e
93
+ if file_data['mime'] == "text/html"
94
+ $stderr.puts "** Ignore file #{url} : #{e.message}"
95
+ next
96
+ end
97
+ end
98
+ files << file_data
99
+ end
100
+
101
+ FileUtils.mkdir_p(self.dest)
102
+ FileUtils.mkdir_p(File.join( self.dest, "META-INF" ))
103
+
104
+ write_epub_file( "content.opf", files )
105
+ write_epub_file( "toc.ncx", files )
106
+ write_epub_file( "mimetype", files )
107
+ write_epub_file( "page-template.xpgt", files )
108
+ write_epub_file( File.join( "META-INF", "container.xml" ) , files )
109
+ if self.config["epub"]["cover-image"]
110
+ write_epub_file( "cover.xhtml", files )
111
+ end
112
+ end
113
+
114
+ # This is a Jekyll[http://jekyllrb.com] extension
115
+ #
116
+ # Write a specific epub file using Liquid. See Jekyll::Site::package_epub
117
+ def write_epub_file( tmpl, files ) #:nodoc:
118
+ $stderr.puts "** Create #{tmpl}"
119
+ template_file = File.join( File.expand_path( File.dirname( __FILE__ ) ), "epub", "templates", tmpl )
120
+ template_content = Liquid::Template.parse(File.open(template_file).read).render( 'epub' => self.config['epub'], 'files' => files )
121
+ File.open( File.join( self.dest, tmpl ), "w+" ).puts template_content
122
+ end
123
+
124
+ # This is a Jekyll[http://jekyllrb.com] extension
125
+ #
126
+ # Very simple post-filters
127
+ #
128
+ # This method need to be rewritten and add the possibility to use user's defined filters
129
+ def apply_epub_filters( files ) #:nodoc:
130
+ files.each do |file|
131
+ file.output = file.output.gsub( /(src\s*=\s*['|"])\//, '\1' )
132
+ file.output = file.output.gsub( /(href\s*=\s*['|"])\//, '\1' )
133
+
134
+ # Remove all <script> tags
135
+ file.output = file.output.gsub( /<script[^>]*>[^<\/script>]*<\/script>/, "" )
136
+ file.output = file.output.gsub( /<script[^>]*\/>/, "" )
137
+ file.output = file.output.gsub( /<noscript>.*<\/noscript>/, "" )
138
+ end
139
+ end
140
+
141
+ # This is a Jekyll[http://jekyllrb.com] extension
142
+ #
143
+ # Create the epub file...
144
+ #
145
+ # WARNING: does not work !!! So please generate the epub file by hand :
146
+ #
147
+ # cd _epub/src
148
+ # zip -Xr9D MyBook.epub mimetype *
149
+ def zip #:nodoc:
150
+ Dir.chdir( self.dest ) do
151
+ filename = self.config['epub']['name']
152
+ filename += ".epub" unless File.extname(filename) == ".epub"
153
+ $stderr.puts "** Create epub file #{filename} in #{Dir.pwd}..."
154
+ %x(zip -Xr9D \"#{filename}\" mimetype *)
155
+ end
156
+ end
157
+ end
158
+
159
+ class Epub
160
+ include Jekyll::Filters
161
+
162
+ DEFAULTS = Jekyll::DEFAULTS.merge( {
163
+ 'destination' => File.join('.', '_epub', 'src'),
164
+ 'permalink' => '/:title.html',
165
+ 'epub' => {
166
+ 'title' => "My Jekyll Blog",
167
+ 'language' => 'en',
168
+ 'identifier' => UUID.generate
169
+ }
170
+ } )
171
+
172
+ # Generate a Jekyll::Epub configuration Hash by merging the default options
173
+ # with anything in _epub.yml, and adding the given options on top
174
+ # +override+ is a Hash of config directives
175
+ #
176
+ # Returns Hash
177
+ def self.configuration(override = {})
178
+ # _epub.yml may override default source location, but until
179
+ # then, we need to know where to look for _config.yml
180
+ source = override['source'] || Jekyll::Epub::DEFAULTS['source']
181
+
182
+ # Get configuration from <source>/_epub.yml
183
+ config_file = File.join(source, '_epub.yml')
184
+ begin
185
+ config = YAML.load_file(config_file)
186
+ raise "Invalid configuration - #{config_file}" if !config.is_a?(Hash)
187
+ $stdout.puts "** Configuration from #{config_file}"
188
+ rescue => err
189
+ $stderr.puts "** WARNING: Could not read configuration. Using defaults (and options)."
190
+ $stderr.puts "\t" + err.to_s
191
+ config = {}
192
+ end
193
+
194
+ # Merge DEFAULTS < _config.yml < override
195
+ Jekyll::Epub::DEFAULTS.deep_merge(config).deep_merge(override)
196
+ end
197
+
198
+ # Generate the epub! All in one!
199
+ def create( override )
200
+ options = Jekyll::Epub.configuration( override )
201
+
202
+ site = Jekyll::Site.new(options)
203
+ site.epub
204
+
205
+ if options['epub']['validate'] == true
206
+ self.validate( site )
207
+ end
208
+ end
209
+
210
+ # A tiny XHTML validator.
211
+ #
212
+ # If you want to validate your xhtml files, juste add
213
+ #
214
+ # epub:
215
+ # validate: true
216
+ #
217
+ # in your _epub.yml file.
218
+ def validate( site )
219
+ begin
220
+ require 'xml/libxml'
221
+ rescue => e
222
+ $stderr.puts "** WARNING: libxml-ruby is not installed. Can't validate!"
223
+ return
224
+ end
225
+
226
+ dtd_file = File.join( File.expand_path( File.dirname( __FILE__ ) ), "epub", "dtd", "xhtml1-strict.dtd" )
227
+ dtd = XML::Dtd.new("-//W3C//DTD XHTML 1.0 Strict//EN", dtd_file)
228
+
229
+ (site.posts + site.pages).each do |path|
230
+ file = File.join( site.dest, path.url )
231
+ $stderr.puts "** Validate #{file}."
232
+ begin
233
+ doc = XML::Document.file(file)
234
+ doc.validate(dtd)
235
+ rescue => e
236
+ $stderr.puts e.message
237
+ end
238
+ end
239
+ end
240
+
241
+ end
242
+ end
@@ -0,0 +1,196 @@
1
+ <!-- Portions (C) International Organization for Standardization 1986
2
+ Permission to copy in any form is granted for use with
3
+ conforming SGML systems and applications as defined in
4
+ ISO 8879, provided this notice is included in all copies.
5
+ -->
6
+ <!-- Character entity set. Typical invocation:
7
+ <!ENTITY % HTMLlat1 PUBLIC
8
+ "-//W3C//ENTITIES Latin 1 for XHTML//EN"
9
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
10
+ %HTMLlat1;
11
+ -->
12
+
13
+ <!ENTITY nbsp "&#160;"> <!-- no-break space = non-breaking space,
14
+ U+00A0 ISOnum -->
15
+ <!ENTITY iexcl "&#161;"> <!-- inverted exclamation mark, U+00A1 ISOnum -->
16
+ <!ENTITY cent "&#162;"> <!-- cent sign, U+00A2 ISOnum -->
17
+ <!ENTITY pound "&#163;"> <!-- pound sign, U+00A3 ISOnum -->
18
+ <!ENTITY curren "&#164;"> <!-- currency sign, U+00A4 ISOnum -->
19
+ <!ENTITY yen "&#165;"> <!-- yen sign = yuan sign, U+00A5 ISOnum -->
20
+ <!ENTITY brvbar "&#166;"> <!-- broken bar = broken vertical bar,
21
+ U+00A6 ISOnum -->
22
+ <!ENTITY sect "&#167;"> <!-- section sign, U+00A7 ISOnum -->
23
+ <!ENTITY uml "&#168;"> <!-- diaeresis = spacing diaeresis,
24
+ U+00A8 ISOdia -->
25
+ <!ENTITY copy "&#169;"> <!-- copyright sign, U+00A9 ISOnum -->
26
+ <!ENTITY ordf "&#170;"> <!-- feminine ordinal indicator, U+00AA ISOnum -->
27
+ <!ENTITY laquo "&#171;"> <!-- left-pointing double angle quotation mark
28
+ = left pointing guillemet, U+00AB ISOnum -->
29
+ <!ENTITY not "&#172;"> <!-- not sign = angled dash,
30
+ U+00AC ISOnum -->
31
+ <!ENTITY shy "&#173;"> <!-- soft hyphen = discretionary hyphen,
32
+ U+00AD ISOnum -->
33
+ <!ENTITY reg "&#174;"> <!-- registered sign = registered trade mark sign,
34
+ U+00AE ISOnum -->
35
+ <!ENTITY macr "&#175;"> <!-- macron = spacing macron = overline
36
+ = APL overbar, U+00AF ISOdia -->
37
+ <!ENTITY deg "&#176;"> <!-- degree sign, U+00B0 ISOnum -->
38
+ <!ENTITY plusmn "&#177;"> <!-- plus-minus sign = plus-or-minus sign,
39
+ U+00B1 ISOnum -->
40
+ <!ENTITY sup2 "&#178;"> <!-- superscript two = superscript digit two
41
+ = squared, U+00B2 ISOnum -->
42
+ <!ENTITY sup3 "&#179;"> <!-- superscript three = superscript digit three
43
+ = cubed, U+00B3 ISOnum -->
44
+ <!ENTITY acute "&#180;"> <!-- acute accent = spacing acute,
45
+ U+00B4 ISOdia -->
46
+ <!ENTITY micro "&#181;"> <!-- micro sign, U+00B5 ISOnum -->
47
+ <!ENTITY para "&#182;"> <!-- pilcrow sign = paragraph sign,
48
+ U+00B6 ISOnum -->
49
+ <!ENTITY middot "&#183;"> <!-- middle dot = Georgian comma
50
+ = Greek middle dot, U+00B7 ISOnum -->
51
+ <!ENTITY cedil "&#184;"> <!-- cedilla = spacing cedilla, U+00B8 ISOdia -->
52
+ <!ENTITY sup1 "&#185;"> <!-- superscript one = superscript digit one,
53
+ U+00B9 ISOnum -->
54
+ <!ENTITY ordm "&#186;"> <!-- masculine ordinal indicator,
55
+ U+00BA ISOnum -->
56
+ <!ENTITY raquo "&#187;"> <!-- right-pointing double angle quotation mark
57
+ = right pointing guillemet, U+00BB ISOnum -->
58
+ <!ENTITY frac14 "&#188;"> <!-- vulgar fraction one quarter
59
+ = fraction one quarter, U+00BC ISOnum -->
60
+ <!ENTITY frac12 "&#189;"> <!-- vulgar fraction one half
61
+ = fraction one half, U+00BD ISOnum -->
62
+ <!ENTITY frac34 "&#190;"> <!-- vulgar fraction three quarters
63
+ = fraction three quarters, U+00BE ISOnum -->
64
+ <!ENTITY iquest "&#191;"> <!-- inverted question mark
65
+ = turned question mark, U+00BF ISOnum -->
66
+ <!ENTITY Agrave "&#192;"> <!-- latin capital letter A with grave
67
+ = latin capital letter A grave,
68
+ U+00C0 ISOlat1 -->
69
+ <!ENTITY Aacute "&#193;"> <!-- latin capital letter A with acute,
70
+ U+00C1 ISOlat1 -->
71
+ <!ENTITY Acirc "&#194;"> <!-- latin capital letter A with circumflex,
72
+ U+00C2 ISOlat1 -->
73
+ <!ENTITY Atilde "&#195;"> <!-- latin capital letter A with tilde,
74
+ U+00C3 ISOlat1 -->
75
+ <!ENTITY Auml "&#196;"> <!-- latin capital letter A with diaeresis,
76
+ U+00C4 ISOlat1 -->
77
+ <!ENTITY Aring "&#197;"> <!-- latin capital letter A with ring above
78
+ = latin capital letter A ring,
79
+ U+00C5 ISOlat1 -->
80
+ <!ENTITY AElig "&#198;"> <!-- latin capital letter AE
81
+ = latin capital ligature AE,
82
+ U+00C6 ISOlat1 -->
83
+ <!ENTITY Ccedil "&#199;"> <!-- latin capital letter C with cedilla,
84
+ U+00C7 ISOlat1 -->
85
+ <!ENTITY Egrave "&#200;"> <!-- latin capital letter E with grave,
86
+ U+00C8 ISOlat1 -->
87
+ <!ENTITY Eacute "&#201;"> <!-- latin capital letter E with acute,
88
+ U+00C9 ISOlat1 -->
89
+ <!ENTITY Ecirc "&#202;"> <!-- latin capital letter E with circumflex,
90
+ U+00CA ISOlat1 -->
91
+ <!ENTITY Euml "&#203;"> <!-- latin capital letter E with diaeresis,
92
+ U+00CB ISOlat1 -->
93
+ <!ENTITY Igrave "&#204;"> <!-- latin capital letter I with grave,
94
+ U+00CC ISOlat1 -->
95
+ <!ENTITY Iacute "&#205;"> <!-- latin capital letter I with acute,
96
+ U+00CD ISOlat1 -->
97
+ <!ENTITY Icirc "&#206;"> <!-- latin capital letter I with circumflex,
98
+ U+00CE ISOlat1 -->
99
+ <!ENTITY Iuml "&#207;"> <!-- latin capital letter I with diaeresis,
100
+ U+00CF ISOlat1 -->
101
+ <!ENTITY ETH "&#208;"> <!-- latin capital letter ETH, U+00D0 ISOlat1 -->
102
+ <!ENTITY Ntilde "&#209;"> <!-- latin capital letter N with tilde,
103
+ U+00D1 ISOlat1 -->
104
+ <!ENTITY Ograve "&#210;"> <!-- latin capital letter O with grave,
105
+ U+00D2 ISOlat1 -->
106
+ <!ENTITY Oacute "&#211;"> <!-- latin capital letter O with acute,
107
+ U+00D3 ISOlat1 -->
108
+ <!ENTITY Ocirc "&#212;"> <!-- latin capital letter O with circumflex,
109
+ U+00D4 ISOlat1 -->
110
+ <!ENTITY Otilde "&#213;"> <!-- latin capital letter O with tilde,
111
+ U+00D5 ISOlat1 -->
112
+ <!ENTITY Ouml "&#214;"> <!-- latin capital letter O with diaeresis,
113
+ U+00D6 ISOlat1 -->
114
+ <!ENTITY times "&#215;"> <!-- multiplication sign, U+00D7 ISOnum -->
115
+ <!ENTITY Oslash "&#216;"> <!-- latin capital letter O with stroke
116
+ = latin capital letter O slash,
117
+ U+00D8 ISOlat1 -->
118
+ <!ENTITY Ugrave "&#217;"> <!-- latin capital letter U with grave,
119
+ U+00D9 ISOlat1 -->
120
+ <!ENTITY Uacute "&#218;"> <!-- latin capital letter U with acute,
121
+ U+00DA ISOlat1 -->
122
+ <!ENTITY Ucirc "&#219;"> <!-- latin capital letter U with circumflex,
123
+ U+00DB ISOlat1 -->
124
+ <!ENTITY Uuml "&#220;"> <!-- latin capital letter U with diaeresis,
125
+ U+00DC ISOlat1 -->
126
+ <!ENTITY Yacute "&#221;"> <!-- latin capital letter Y with acute,
127
+ U+00DD ISOlat1 -->
128
+ <!ENTITY THORN "&#222;"> <!-- latin capital letter THORN,
129
+ U+00DE ISOlat1 -->
130
+ <!ENTITY szlig "&#223;"> <!-- latin small letter sharp s = ess-zed,
131
+ U+00DF ISOlat1 -->
132
+ <!ENTITY agrave "&#224;"> <!-- latin small letter a with grave
133
+ = latin small letter a grave,
134
+ U+00E0 ISOlat1 -->
135
+ <!ENTITY aacute "&#225;"> <!-- latin small letter a with acute,
136
+ U+00E1 ISOlat1 -->
137
+ <!ENTITY acirc "&#226;"> <!-- latin small letter a with circumflex,
138
+ U+00E2 ISOlat1 -->
139
+ <!ENTITY atilde "&#227;"> <!-- latin small letter a with tilde,
140
+ U+00E3 ISOlat1 -->
141
+ <!ENTITY auml "&#228;"> <!-- latin small letter a with diaeresis,
142
+ U+00E4 ISOlat1 -->
143
+ <!ENTITY aring "&#229;"> <!-- latin small letter a with ring above
144
+ = latin small letter a ring,
145
+ U+00E5 ISOlat1 -->
146
+ <!ENTITY aelig "&#230;"> <!-- latin small letter ae
147
+ = latin small ligature ae, U+00E6 ISOlat1 -->
148
+ <!ENTITY ccedil "&#231;"> <!-- latin small letter c with cedilla,
149
+ U+00E7 ISOlat1 -->
150
+ <!ENTITY egrave "&#232;"> <!-- latin small letter e with grave,
151
+ U+00E8 ISOlat1 -->
152
+ <!ENTITY eacute "&#233;"> <!-- latin small letter e with acute,
153
+ U+00E9 ISOlat1 -->
154
+ <!ENTITY ecirc "&#234;"> <!-- latin small letter e with circumflex,
155
+ U+00EA ISOlat1 -->
156
+ <!ENTITY euml "&#235;"> <!-- latin small letter e with diaeresis,
157
+ U+00EB ISOlat1 -->
158
+ <!ENTITY igrave "&#236;"> <!-- latin small letter i with grave,
159
+ U+00EC ISOlat1 -->
160
+ <!ENTITY iacute "&#237;"> <!-- latin small letter i with acute,
161
+ U+00ED ISOlat1 -->
162
+ <!ENTITY icirc "&#238;"> <!-- latin small letter i with circumflex,
163
+ U+00EE ISOlat1 -->
164
+ <!ENTITY iuml "&#239;"> <!-- latin small letter i with diaeresis,
165
+ U+00EF ISOlat1 -->
166
+ <!ENTITY eth "&#240;"> <!-- latin small letter eth, U+00F0 ISOlat1 -->
167
+ <!ENTITY ntilde "&#241;"> <!-- latin small letter n with tilde,
168
+ U+00F1 ISOlat1 -->
169
+ <!ENTITY ograve "&#242;"> <!-- latin small letter o with grave,
170
+ U+00F2 ISOlat1 -->
171
+ <!ENTITY oacute "&#243;"> <!-- latin small letter o with acute,
172
+ U+00F3 ISOlat1 -->
173
+ <!ENTITY ocirc "&#244;"> <!-- latin small letter o with circumflex,
174
+ U+00F4 ISOlat1 -->
175
+ <!ENTITY otilde "&#245;"> <!-- latin small letter o with tilde,
176
+ U+00F5 ISOlat1 -->
177
+ <!ENTITY ouml "&#246;"> <!-- latin small letter o with diaeresis,
178
+ U+00F6 ISOlat1 -->
179
+ <!ENTITY divide "&#247;"> <!-- division sign, U+00F7 ISOnum -->
180
+ <!ENTITY oslash "&#248;"> <!-- latin small letter o with stroke,
181
+ = latin small letter o slash,
182
+ U+00F8 ISOlat1 -->
183
+ <!ENTITY ugrave "&#249;"> <!-- latin small letter u with grave,
184
+ U+00F9 ISOlat1 -->
185
+ <!ENTITY uacute "&#250;"> <!-- latin small letter u with acute,
186
+ U+00FA ISOlat1 -->
187
+ <!ENTITY ucirc "&#251;"> <!-- latin small letter u with circumflex,
188
+ U+00FB ISOlat1 -->
189
+ <!ENTITY uuml "&#252;"> <!-- latin small letter u with diaeresis,
190
+ U+00FC ISOlat1 -->
191
+ <!ENTITY yacute "&#253;"> <!-- latin small letter y with acute,
192
+ U+00FD ISOlat1 -->
193
+ <!ENTITY thorn "&#254;"> <!-- latin small letter thorn,
194
+ U+00FE ISOlat1 -->
195
+ <!ENTITY yuml "&#255;"> <!-- latin small letter y with diaeresis,
196
+ U+00FF ISOlat1 -->
@@ -0,0 +1,80 @@
1
+ <!-- Special characters for XHTML -->
2
+
3
+ <!-- Character entity set. Typical invocation:
4
+ <!ENTITY % HTMLspecial PUBLIC
5
+ "-//W3C//ENTITIES Special for XHTML//EN"
6
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
7
+ %HTMLspecial;
8
+ -->
9
+
10
+ <!-- Portions (C) International Organization for Standardization 1986:
11
+ Permission to copy in any form is granted for use with
12
+ conforming SGML systems and applications as defined in
13
+ ISO 8879, provided this notice is included in all copies.
14
+ -->
15
+
16
+ <!-- Relevant ISO entity set is given unless names are newly introduced.
17
+ New names (i.e., not in ISO 8879 list) do not clash with any
18
+ existing ISO 8879 entity names. ISO 10646 character numbers
19
+ are given for each character, in hex. values are decimal
20
+ conversions of the ISO 10646 values and refer to the document
21
+ character set. Names are Unicode names.
22
+ -->
23
+
24
+ <!-- C0 Controls and Basic Latin -->
25
+ <!ENTITY quot "&#34;"> <!-- quotation mark, U+0022 ISOnum -->
26
+ <!ENTITY amp "&#38;#38;"> <!-- ampersand, U+0026 ISOnum -->
27
+ <!ENTITY lt "&#38;#60;"> <!-- less-than sign, U+003C ISOnum -->
28
+ <!ENTITY gt "&#62;"> <!-- greater-than sign, U+003E ISOnum -->
29
+ <!ENTITY apos "&#39;"> <!-- apostrophe = APL quote, U+0027 ISOnum -->
30
+
31
+ <!-- Latin Extended-A -->
32
+ <!ENTITY OElig "&#338;"> <!-- latin capital ligature OE,
33
+ U+0152 ISOlat2 -->
34
+ <!ENTITY oelig "&#339;"> <!-- latin small ligature oe, U+0153 ISOlat2 -->
35
+ <!-- ligature is a misnomer, this is a separate character in some languages -->
36
+ <!ENTITY Scaron "&#352;"> <!-- latin capital letter S with caron,
37
+ U+0160 ISOlat2 -->
38
+ <!ENTITY scaron "&#353;"> <!-- latin small letter s with caron,
39
+ U+0161 ISOlat2 -->
40
+ <!ENTITY Yuml "&#376;"> <!-- latin capital letter Y with diaeresis,
41
+ U+0178 ISOlat2 -->
42
+
43
+ <!-- Spacing Modifier Letters -->
44
+ <!ENTITY circ "&#710;"> <!-- modifier letter circumflex accent,
45
+ U+02C6 ISOpub -->
46
+ <!ENTITY tilde "&#732;"> <!-- small tilde, U+02DC ISOdia -->
47
+
48
+ <!-- General Punctuation -->
49
+ <!ENTITY ensp "&#8194;"> <!-- en space, U+2002 ISOpub -->
50
+ <!ENTITY emsp "&#8195;"> <!-- em space, U+2003 ISOpub -->
51
+ <!ENTITY thinsp "&#8201;"> <!-- thin space, U+2009 ISOpub -->
52
+ <!ENTITY zwnj "&#8204;"> <!-- zero width non-joiner,
53
+ U+200C NEW RFC 2070 -->
54
+ <!ENTITY zwj "&#8205;"> <!-- zero width joiner, U+200D NEW RFC 2070 -->
55
+ <!ENTITY lrm "&#8206;"> <!-- left-to-right mark, U+200E NEW RFC 2070 -->
56
+ <!ENTITY rlm "&#8207;"> <!-- right-to-left mark, U+200F NEW RFC 2070 -->
57
+ <!ENTITY ndash "&#8211;"> <!-- en dash, U+2013 ISOpub -->
58
+ <!ENTITY mdash "&#8212;"> <!-- em dash, U+2014 ISOpub -->
59
+ <!ENTITY lsquo "&#8216;"> <!-- left single quotation mark,
60
+ U+2018 ISOnum -->
61
+ <!ENTITY rsquo "&#8217;"> <!-- right single quotation mark,
62
+ U+2019 ISOnum -->
63
+ <!ENTITY sbquo "&#8218;"> <!-- single low-9 quotation mark, U+201A NEW -->
64
+ <!ENTITY ldquo "&#8220;"> <!-- left double quotation mark,
65
+ U+201C ISOnum -->
66
+ <!ENTITY rdquo "&#8221;"> <!-- right double quotation mark,
67
+ U+201D ISOnum -->
68
+ <!ENTITY bdquo "&#8222;"> <!-- double low-9 quotation mark, U+201E NEW -->
69
+ <!ENTITY dagger "&#8224;"> <!-- dagger, U+2020 ISOpub -->
70
+ <!ENTITY Dagger "&#8225;"> <!-- double dagger, U+2021 ISOpub -->
71
+ <!ENTITY permil "&#8240;"> <!-- per mille sign, U+2030 ISOtech -->
72
+ <!ENTITY lsaquo "&#8249;"> <!-- single left-pointing angle quotation mark,
73
+ U+2039 ISO proposed -->
74
+ <!-- lsaquo is proposed but not yet ISO standardized -->
75
+ <!ENTITY rsaquo "&#8250;"> <!-- single right-pointing angle quotation mark,
76
+ U+203A ISO proposed -->
77
+ <!-- rsaquo is proposed but not yet ISO standardized -->
78
+
79
+ <!-- Currency Symbols -->
80
+ <!ENTITY euro "&#8364;"> <!-- euro sign, U+20AC NEW -->