1 # Copyright 2015-2017 ARM Limited 2 # Copyright 2016 Google Inc. All Rights Reserved. 3 # 4 # Licensed under the Apache License, Version 2.0 (the "License"); 5 # you may not use this file except in compliance with the License. 6 # You may obtain a copy of the License at 7 # 8 # http://www.apache.org/licenses/LICENSE-2.0 9 # 10 # Unless required by applicable law or agreed to in writing, software 11 # distributed under the License is distributed on an "AS IS" BASIS, 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 # 16 """Preprocessor to remove Marked Lines from IPython Output Cells""" 17 18 19 from nbconvert.exporters.html import HTMLExporter 20 from nbconvert.preprocessors import Preprocessor 21 import os 22 import re 23 24 REMOVE_START = '/* TRAPPY_PUBLISH_REMOVE_START */' 25 REMOVE_STOP = '/* TRAPPY_PUBLISH_REMOVE_STOP */' 26 REMOVE_LINE = '/* TRAPPY_PUBLISH_REMOVE_LINE */' 27 IMPORT_SCRIPT = r'/\* TRAPPY_PUBLISH_IMPORT = "([^"]+)" \*/' 28 SOURCE_LIB = r'<!-- TRAPPY_PUBLISH_SOURCE_LIB = "([^"]+)" -->' 29 30 31 class HTML(HTMLExporter): 32 """HTML Exporter class for TRAPpy notebooks""" 33 34 def __init__(self, **kwargs): 35 super(HTML, self).__init__(**kwargs) 36 self.register_preprocessor(TrappyPlotterPreprocessor, enabled=True) 37 38 39 class TrappyPlotterPreprocessor(Preprocessor): 40 """Preprocessor to remove Marked Lines from IPython Output Cells""" 41 42 def __init__(self, *args, **kwargs): 43 super(Preprocessor, self).__init__(*args, **kwargs) 44 self.inlined_files = [] 45 self.sourced_libs = [] 46 47 def preprocess_cell(self, cell, resources, cell_index): 48 """Check if cell has text/html output and filter it""" 49 50 if cell.cell_type == 'code' and hasattr(cell, "outputs"): 51 for output in cell.outputs: 52 if output.output_type == "display_data" and \ 53 hasattr( output.data, "text/html"): 54 filtered = self.filter_output(output.data["text/html"]) 55 output.data["text/html"] = filtered 56 return cell, resources 57 58 def filter_output(self, output): 59 """Function to remove marked lines""" 60 61 lines = output.split('\n') 62 63 final_lines = [] 64 multi_line_remove = False 65 for line in lines: 66 if REMOVE_START in line: 67 multi_line_remove = True 68 continue 69 if REMOVE_STOP in line: 70 multi_line_remove = False 71 continue 72 if multi_line_remove or REMOVE_LINE in line: 73 continue 74 75 import_match = re.search(IMPORT_SCRIPT, line) 76 if import_match: 77 trappy_base = os.path.dirname(os.path.dirname(__file__)) 78 import_file = os.path.join(trappy_base, import_match.group(1)) 79 if import_file in self.inlined_files: 80 continue 81 82 with open(import_file) as fin: 83 final_lines.extend([l[:-1] for l in fin.readlines()]) 84 85 self.inlined_files.append(import_file) 86 continue 87 88 source_match = re.search(SOURCE_LIB, line) 89 if source_match: 90 lib_url = source_match.group(1) 91 if lib_url in self.sourced_libs: 92 continue 93 94 scl = '<script src="{}" type="text/javascript" charset="utf-8"></script>'.\ 95 format(lib_url) 96 final_lines.append(scl) 97 98 self.sourced_libs.append(lib_url) 99 continue 100 101 final_lines.append(line) 102 103 return '\n'.join(final_lines) 104