Class: IpynbDiff::Transformer

Inherits:
Object
  • Object
show all
Defined in:
lib/transformer.rb

Overview

Returns a markdown version of the Jupyter Notebook

Instance Method Summary collapse

Constructor Details

#initialize(include_metadata: TRUE, cell_decorator: :html) ⇒ Transformer

Returns a new instance of Transformer.



15
16
17
18
# File 'lib/transformer.rb', line 15

def initialize(include_metadata: TRUE, cell_decorator: :html)
  @include_metadata = 
  @cell_decorator = cell_decorator
end

Instance Method Details

#decorate_cell(rows, cell) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/transformer.rb', line 40

def decorate_cell(rows, cell)
  tags = cell['metadata']&.fetch('tags', [])
  type = cell['cell_type'] || 'raw'

  case @cell_decorator
  when :html
    rows.prepend(%(<div class="cell #{type}" data-id="#{cell['id']}" data-tags="#{tags&.join(' ')}">\n\n))
        .append("\n</div>\n")
  when :percent
    rows.prepend(%(%% Cell type:#{type} id:#{cell['id']} tags:#{tags&.join(',')}\n\n))
  else
    rows
  end.join('')
end

#decorate_output(output_rows, output) ⇒ Object



59
60
61
62
63
64
65
# File 'lib/transformer.rb', line 59

def decorate_output(output_rows, output)
  if @cell_decorator == :html
    output_rows.prepend(%(\n<div class="output #{output['output_type']}">\n\n)).append("\n</div>\n")
  else
    output_rows.prepend(%(\n%%%% Output: #{output['output_type']}\n\n))
  end
end

#format_traceback(traceback) ⇒ Object



76
77
78
79
80
81
82
# File 'lib/transformer.rb', line 76

def format_traceback(traceback)
  traceback.map do |t|
    t.split("\n").map do |line|
      line.gsub(/\[[0-9][0-9;]*m/, '').sub("\u001B", '    ').gsub(/\u001B/, '').rstrip << "\n"
    end
  end
end

#transform(notebook) ⇒ Object



30
31
32
33
34
35
36
37
38
# File 'lib/transformer.rb', line 30

def transform(notebook)
  notebook_json = validate_notebook(notebook)
  transformed_blocks = notebook_json['cells'].map do |cell|
    decorate_cell(transform_cell(cell, notebook_json), cell)
  end

  transformed_blocks.prepend((notebook_json)) if @include_metadata
  transformed_blocks.join("\n")
end

#transform_cell(cell, notebook) ⇒ Object



55
56
57
# File 'lib/transformer.rb', line 55

def transform_cell(cell, notebook)
  cell['cell_type'] == 'code' ? transform_code_cell(cell, notebook) : transform_text_cell(cell)
end

#transform_code_cell(cell, notebook) ⇒ Object



67
68
69
70
71
72
73
74
# File 'lib/transformer.rb', line 67

def transform_code_cell(cell, notebook)
  [
    %(``` #{notebook['metadata']['kernelspec']['language']}\n),
    *cell['source'],
    "\n```\n",
    *cell['outputs'].map { |output| transform_output(output) }
  ]
end

#transform_error_result(output) ⇒ Object



94
95
96
# File 'lib/transformer.rb', line 94

def transform_error_result(output)
  format_traceback(output['traceback'])
end

#transform_execute_result(output) ⇒ Object



84
85
86
# File 'lib/transformer.rb', line 84

def transform_execute_result(output)
  output['data']['text/plain'].map { |line| "    #{line}" }.append("\n")
end

#transform_image_result(output) ⇒ Object



88
89
90
91
92
# File 'lib/transformer.rb', line 88

def transform_image_result(output)
  if output['data'].key?('image/png')
    ["![](data:image/png;base64,#{output['data']['image/png'].gsub("\n", '')})", "\n"]
  end
end

#transform_metadata(notebook_json) ⇒ Object



116
117
118
119
120
121
122
123
124
125
# File 'lib/transformer.rb', line 116

def (notebook_json)
  {
    'jupyter' => {
      'kernelspec' => notebook_json['metadata']['kernelspec'],
      'language_info' => notebook_json['metadata']['language_info'],
      'nbformat' => notebook_json['nbformat'],
      'nbformat_minor' => notebook_json['nbformat_minor']
    }
  }.to_yaml + "---\n"
end

#transform_output(output) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/transformer.rb', line 98

def transform_output(output)
  transformed =
    case output['output_type']
    when 'execute_result'
      transform_execute_result(output)
    when 'display_data'
      transform_image_result(output)
    when 'error'
      transform_error_result(output)
    end

  decorate_output(transformed, output).join('') if transformed
end

#transform_text_cell(cell) ⇒ Object



112
113
114
# File 'lib/transformer.rb', line 112

def transform_text_cell(cell)
  cell['source'].append("\n")
end

#validate_notebook(notebook) ⇒ Object



20
21
22
23
24
25
26
27
28
# File 'lib/transformer.rb', line 20

def validate_notebook(notebook)
  notebook_json = JSON.parse(notebook)

  return notebook_json if notebook_json.key?('cells') && notebook_json.key?('metadata')

  raise InvalidNotebookError
rescue JSON::ParserError
  raise InvalidNotebookError
end