Class: IpynbDiff::Transformer

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

Overview

Returns a markdown version of the Jupyter Notebook

Instance Method Summary collapse

Methods included from SymbolizedMarkdownHelper

#_, #array_if_not_array, #symbolize_array

Constructor Details

#initialize(include_frontmatter: true) ⇒ Transformer

Returns a new instance of Transformer.



19
20
21
22
# File 'lib/transformer.rb', line 19

def initialize(include_frontmatter: true)
  @include_frontmatter = include_frontmatter
  @output_transformer = OutputTransformer.new
end

Instance Method Details

#decorate_cell(rows, cell, symbol) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/transformer.rb', line 61

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

  [
    symbol, %(%% Cell type:#{type} id:#{cell['id']} tags:#{tags&.join(',')}),
    _,
    *rows,
    _
  ]
end

#transform(notebook) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/transformer.rb', line 34

def transform(notebook)
  return TransformedNotebook.new unless notebook

  notebook_json = validate_notebook(notebook)
  transformed = transform_document(notebook_json)
  symbol_map = IpynbSymbolMap.parse(notebook)

  symbols, lines = if transformed && !transformed.empty?
                     transformed.partition.each_with_index { |_el, i| i.even? }
                   else
                     [[], []]
                   end

  TransformedNotebook.new(lines, symbols, symbol_map)
end

#transform_cell(cell, notebook, symbol) ⇒ Object



73
74
75
# File 'lib/transformer.rb', line 73

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

#transform_code_cell(cell, notebook, symbol) ⇒ Object



77
78
79
80
81
82
83
84
85
86
# File 'lib/transformer.rb', line 77

def transform_code_cell(cell, notebook, symbol)
  [
    symbol / 'source', %(``` #{notebook.dig('metadata', 'kernelspec', 'language') || ''}),
    symbolize_array(symbol / 'source', cell['source'], &:rstrip),
    _('```'),
    cell['outputs'].map.with_index do |output, idx|
      @output_transformer.transform(output, symbol / ['outputs', idx])
    end
  ]
end

#transform_document(notebook) ⇒ Object



50
51
52
53
54
55
56
57
58
59
# File 'lib/transformer.rb', line 50

def transform_document(notebook)
  symbol = JsonSymbol.new('.cells')

  transformed_blocks = notebook['cells'].map.with_index do |cell, idx|
    decorate_cell(transform_cell(cell, notebook, symbol / idx), cell, symbol / idx)
  end

  transformed_blocks.prepend((notebook)) if @include_frontmatter
  transformed_blocks.flatten
end

#transform_metadata(notebook_json) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/transformer.rb', line 92

def (notebook_json)
  as_yaml = {
    '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

  as_yaml.split("\n").map { |l| _(l) }.append(_('---'), _)
end

#transform_text_cell(cell, symbol) ⇒ Object



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

def transform_text_cell(cell, symbol)
  symbolize_array(symbol / 'source', cell['source'], &:rstrip)
end

#validate_notebook(notebook) ⇒ Object



24
25
26
27
28
29
30
31
32
# File 'lib/transformer.rb', line 24

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

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

  raise InvalidNotebookError
rescue JSON::ParserError
  raise InvalidNotebookError
end