pandocfilters 0.0.1.alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d03820dd1432a65258ce231a8c33965755bd6d7e
4
+ data.tar.gz: 3539e051a195ada06037daa752569b618033e725
5
+ SHA512:
6
+ metadata.gz: babf25b565f5fcb466f38afcb7baeecfc81c18a24f48c6fc473350803ddb2f028ea1d78ffdc81b981a4e16fdd1462aaf2423aa554ffeeb7654da91bacbe8d11c
7
+ data.tar.gz: 0da641977ceace8e8802afddb0a57bc8a99472188045b13b05d70da9b89a7670b4aee29c0616dd90b1a0d48f4dcef6486c8bd254127a477abdfb9fd53e8c03de
@@ -0,0 +1,115 @@
1
+ require 'json'
2
+ require_relative 'pandocfilters/node'
3
+
4
+ module PandocFilters
5
+
6
+ # Fetch prebuild filter.
7
+ #
8
+ # @param name [String] Filter name.
9
+ # @return [String] Path to the filter.
10
+ def self.filter(name)
11
+ glob = File.expand_path('../pandocfilters/filters/*' ,__FILE__)
12
+ filters = Dir.glob(glob).map { |f| File.basename(f) }
13
+
14
+ raise "No build-in filter names #{name}" unless filters.include?(name)
15
+
16
+ File.expand_path("../pandocfilters/filters/#{name}" ,__FILE__)
17
+ end
18
+
19
+ # Converts an action into a filter that reads a JSON-formatted
20
+ # pandoc document from stdin, transforms it by walking the tree
21
+ # with the action, and returns a new JSON-formatted pandoc document
22
+ # to stdout. The argument is a function action(key, value, format, meta),
23
+ # where key is the type of the pandoc object (e.g. 'Str', 'Para'),
24
+ # value is the contents of the object (e.g. a string for 'Str',
25
+ # a list of inline elements for 'Para'), format is the target
26
+ # output format (which will be taken for the first command line
27
+ # argument if present), and meta is the document's metadata.
28
+ # If the function returns None, the object to which it applies
29
+ # will remain unchanged. If it returns an object, the object will
30
+ # be replaced. If it returns a list, the list will be spliced in to
31
+ # the list to which the target object belongs. (So, returning an
32
+ # empty list deletes the object.)
33
+ #
34
+ # action Callable object
35
+ #
36
+ # Return Manuplated JSON
37
+ def self.process(&action)
38
+ doc = JSON.load($stdin.read)
39
+ if ARGV.size > 1
40
+ format = ARGV[1]
41
+ else
42
+ format = ""
43
+ end
44
+ altered = self.walk(doc, format, doc[0]['unMeta'], &action)
45
+ JSON.dump(altered, $stdout)
46
+ end
47
+
48
+ # Walks the tree x and returns concatenated string content,
49
+ # leaving out all formatting.
50
+ def self.stringify(x)
51
+ result = []
52
+
53
+ go = lambda do |key, val, format, meta|
54
+ if ['Str', 'MetaString'].include? key
55
+ result.push(val)
56
+ elsif key == 'Code'
57
+ result.push(val[1])
58
+ elsif key == 'Math'
59
+ result.push(val[1])
60
+ elsif key == 'LineBreak'
61
+ result.push(" ")
62
+ elsif key == 'Space'
63
+ result.push(" ")
64
+ end
65
+ end
66
+
67
+ self.walk(x, "", {}, &go)
68
+
69
+ result.join('')
70
+ end
71
+
72
+ # Returns an attribute list, constructed from the
73
+ # dictionary attrs.
74
+ def attributes(attrs)
75
+ attrs ||= {}
76
+ ident = attrs.fetch('id', '')
77
+ classes = attrs.fetch("classes", [])
78
+ keyvals = []
79
+ attrs.keep_if { |k, v| k != "classes" && k != "id" }.each do |k, v|
80
+ keyvals << [k, v]
81
+ end
82
+
83
+ [ident, classes, keyvals]
84
+ end
85
+
86
+ # Walk a tree, applying an action to every object.
87
+ # Returns a modified tree.
88
+ def self.walk(x, format, meta, &action)
89
+ if x.is_a? Array
90
+ array = []
91
+ x.each do |item|
92
+ if item.is_a?(Hash) && item.has_key?('t')
93
+ res = action.call(item['t'], item['c'], format, meta)
94
+ if res.nil?
95
+ array.push(self.walk(item, format, meta, &action))
96
+ elsif res.is_a? Array
97
+ res.each { |z| array.push(self.walk(z, format, meta, &action)) }
98
+ else
99
+ array.push(self.walk(res, format, meta, &action))
100
+ end
101
+ else
102
+ array.push(self.walk(item, format, meta, &action))
103
+ end
104
+ end
105
+ return array
106
+ elsif x.is_a? Hash
107
+ hash = {}
108
+ x.each { |k, _| hash[k] = self.walk(x[k], format, meta, &action) }
109
+ return hash
110
+ else
111
+ return x
112
+ end
113
+ end
114
+
115
+ end
@@ -0,0 +1,11 @@
1
+ class String
2
+
3
+ # Strips off underscores in string, then capitalize each words.
4
+ #
5
+ # @return [String] Camelized string.
6
+ def camelize
7
+ string = self
8
+ string.split('_').map(&:capitalize).join('')
9
+ end
10
+
11
+ end
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Paragraph starts with `CITE:' act like blockquote cite.
4
+ # Align the cite to right.
5
+
6
+ require 'pandocfilters'
7
+
8
+ filter = lambda do |key, value, format, meta|
9
+ if key == 'Para' && (cite = PandocFilters.stringify(value)).start_with?('CITE:')
10
+ cite.sub!(/CITE:\s?/, '')
11
+ xml = %(<w:p>
12
+ <w:pPr>
13
+ <w:pStyle w:val="BlockquoteCite"/>
14
+ </w:pPr>
15
+ <w:r>
16
+ <w:t xml:space="preserve">#{cite}</w:t>
17
+ </w:r>
18
+ </w:p>)
19
+
20
+ return PandocFilters::Node.raw_block('openxml', xml)
21
+ end
22
+ end
23
+
24
+ PandocFilters.process &filter
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Identify paragraph starts with `DEDICATION:' as dedication.
4
+ # Then replace the dedication with raw OOXML xml, and trip off the `DEDICATION:'.
5
+ # THe dedication is placed on a new page, and center aligned.
6
+
7
+ require 'pandocfilters'
8
+
9
+ filter = lambda do |key, value, format, meta|
10
+ if key == 'Para'
11
+ if value[0]['c'] == 'DEDICATION:'
12
+ dedication = PandocFilters.stringify(value).sub(/DEDICATION:\s?/, '')
13
+ xml = %(<w:p>
14
+ <w:pPr>
15
+ <w:pStyle w:val="DedicationText"/>
16
+ </w:pPr>
17
+ <w:r>
18
+ <w:t xml:space="preserve">#{dedication}</w:t>
19
+ </w:r>
20
+ </w:p>)
21
+
22
+ PandocFilters::Node.raw_block('openxml', xml)
23
+ elsif value[0]['c'] == 'DEDICATION_FIRST:'
24
+ dedication = PandocFilters.stringify(value).sub(/DEDICATION_FIRST:\s?/, '')
25
+ xml = %(<w:p>
26
+ <w:pPr>
27
+ <w:pStyle w:val="DedicationTextFirst"/>
28
+ </w:pPr>
29
+ <w:r>
30
+ <w:t xml:space="preserve">#{dedication}</w:t>
31
+ </w:r>
32
+ </w:p>)
33
+
34
+ PandocFilters::Node.raw_block('openxml', xml)
35
+ end
36
+ end
37
+ end
38
+
39
+ PandocFilters.process &filter
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Identify paragraph contains `<!--PAGEBREAK-->' as page break in docx.
4
+ # Then replace the page break with raw OOXML xml'.
5
+
6
+ require 'pandocfilters'
7
+
8
+ filter = lambda do |key, value, format, meta|
9
+ if key == 'RawBlock' && value[1] == '<!--PAGEBREAK-->'
10
+ xml = %(<w:p><w:r><w:br w:type="page"/></w:r></w:p>)
11
+
12
+ return PandocFilters::Node.raw_block('openxml', xml)
13
+ end
14
+ end
15
+
16
+ PandocFilters.process &filter
@@ -0,0 +1,80 @@
1
+ require_relative 'core_ext/string'
2
+
3
+ module PandocFilters
4
+ class Node
5
+ # Pandoc build-in node types
6
+ # see http://hackage.haskell.org/package/pandoc-types-1.12.4.3/docs/Text-Pandoc-Definition.html
7
+ #
8
+ # key: node type
9
+ # value: expected arguments number
10
+ NODES = {
11
+ # block elements
12
+ plain: 1,
13
+ para: 1,
14
+ code_block: 2,
15
+ raw_block: 2,
16
+ block_quote: 1,
17
+ ordered_list: 2,
18
+ bullet_list: 1,
19
+ definition_list: 1,
20
+ header: 3,
21
+ horizontal_rule: 0,
22
+ table: 5,
23
+ div: 2,
24
+ null: 0,
25
+
26
+ # inline elements
27
+ str: 1,
28
+ emph: 1,
29
+ strong: 1,
30
+ strikeout: 1,
31
+ superscript: 1,
32
+ subscript: 1,
33
+ small_caps: 1,
34
+ quoted: 2,
35
+ cite: 2,
36
+ code: 2,
37
+ space: 0,
38
+ line_break: 0,
39
+ math: 2,
40
+ raw_inline: 2,
41
+ link: 2,
42
+ image: 2,
43
+ note: 1,
44
+ span: 2
45
+ }
46
+
47
+ class << self
48
+ def method_missing(name, *args)
49
+ raise "undefined #{name} node type" unless NODES.keys.include?(name)
50
+ unless args.size == NODES[name]
51
+ raise "#{name} expects #{NODES[name]} arguments, but given #{args.size}"
52
+ end
53
+
54
+ new(name.to_s.camelize, *args).to_hash
55
+ end
56
+ end
57
+
58
+ attr_reader :type
59
+ attr_reader :args
60
+
61
+ def initialize(type, *args)
62
+ @type = type
63
+ @args = args
64
+ end
65
+
66
+ def to_hash
67
+ xs = case args.size
68
+ when 0
69
+ []
70
+ when 1
71
+ args[0]
72
+ else
73
+ args
74
+ end
75
+
76
+ {'t': type, 'c': xs}
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,3 @@
1
+ module PandocFilters
2
+ VERSION = '0.0.1.alpha'
3
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pandocfilters
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.alpha
5
+ platform: ruby
6
+ authors:
7
+ - Andor Chen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 10.4.2
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 10.4.2
27
+ description: A Ruby gem for writing pandoc filters.
28
+ email: andor.chen.27@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - lib/pandocfilters.rb
34
+ - lib/pandocfilters/core_ext/string.rb
35
+ - lib/pandocfilters/filters/blockquote_cite
36
+ - lib/pandocfilters/filters/dedication
37
+ - lib/pandocfilters/filters/page_break
38
+ - lib/pandocfilters/node.rb
39
+ - lib/pandocfilters/version.rb
40
+ homepage: https://github.com/andorchen/pandocfilters.rb
41
+ licenses:
42
+ - MIT
43
+ metadata: {}
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.9.3
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">"
56
+ - !ruby/object:Gem::Version
57
+ version: 1.3.1
58
+ requirements:
59
+ - pandoc >= 1.14
60
+ rubyforge_project:
61
+ rubygems_version: 2.4.5
62
+ signing_key:
63
+ specification_version: 2
64
+ summary: A Ruby gem for writing pandoc filters.
65
+ test_files: []