Compare commits
	
		
			No commits in common. "master" and "v0.1.0-beta.7" have entirely different histories.
		
	
	
		
			
				master
			
			...
			
				v0.1.0-bet
			
		
	
		
					 64 changed files with 3046 additions and 4970 deletions
				
			
		| 
						 | 
				
			
			@ -1,11 +1,8 @@
 | 
			
		|||
node_modules/
 | 
			
		||||
/.*cache/
 | 
			
		||||
/.tmp/
 | 
			
		||||
/coverage/
 | 
			
		||||
/dist/
 | 
			
		||||
/packages/*/bin/
 | 
			
		||||
/packages/*/coverage/
 | 
			
		||||
/packages/*/dist/
 | 
			
		||||
/packages/*/lib/
 | 
			
		||||
/packages/*/*.js
 | 
			
		||||
/scripts/*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										103
									
								
								.eslintrc.js
									
										
									
									
									
								
							
							
						
						
									
										103
									
								
								.eslintrc.js
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,4 @@
 | 
			
		|||
const tsconfigs = [
 | 
			
		||||
  'tsconfig.json',
 | 
			
		||||
  '*/tsconfig.json',
 | 
			
		||||
  'packages/*/tsconfig.json',
 | 
			
		||||
  'packages/*/test/tsconfig.json',
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			@ -20,14 +18,15 @@ module.exports = {
 | 
			
		|||
  },
 | 
			
		||||
  settings: {
 | 
			
		||||
    'import/resolver': {
 | 
			
		||||
      // Use eslint-import-resolver-typescript to obey "paths" in tsconfig.json.
 | 
			
		||||
      typescript: {
 | 
			
		||||
      // Use eslint-import-resolver-ts to obey "paths" in tsconfig.json.
 | 
			
		||||
      ts: {
 | 
			
		||||
        directory: tsconfigs,
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  extends: [
 | 
			
		||||
    'eslint:recommended',
 | 
			
		||||
    'plugin:@typescript-eslint/eslint-recommended',
 | 
			
		||||
    'plugin:@typescript-eslint/recommended',
 | 
			
		||||
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
 | 
			
		||||
    'standard-with-typescript',
 | 
			
		||||
| 
						 | 
				
			
			@ -36,63 +35,48 @@ module.exports = {
 | 
			
		|||
  ],
 | 
			
		||||
  rules: {
 | 
			
		||||
    'comma-dangle': ['error', 'always-multiline'],
 | 
			
		||||
    // Disable in favour of TypeScript rule.
 | 
			
		||||
    'func-call-spacing': 'off',
 | 
			
		||||
    'linebreak-style': ['error', 'unix'],
 | 
			
		||||
    // Changed from error to warn and enabled ignoreEOLComments.
 | 
			
		||||
    'lines-between-class-members': 'off',
 | 
			
		||||
    // Disable in favour of TypeScript rule.
 | 
			
		||||
    'no-extra-semi': 'off',
 | 
			
		||||
    'no-multi-spaces': ['warn', {
 | 
			
		||||
      ignoreEOLComments: true,
 | 
			
		||||
    }],
 | 
			
		||||
    // Changed from error to warn and adjusted options.
 | 
			
		||||
    'no-multiple-empty-lines': ['warn', {
 | 
			
		||||
      max: 2,
 | 
			
		||||
      maxEOF: 1,
 | 
			
		||||
      maxBOF: 1,
 | 
			
		||||
    }],
 | 
			
		||||
    'no-template-curly-in-string': 'off',
 | 
			
		||||
    // Changed from 'after' to 'before'.
 | 
			
		||||
    'operator-linebreak': ['error', 'before'],
 | 
			
		||||
    // Changed from error and all 'never' to warn and switches 'never'.
 | 
			
		||||
    'padded-blocks': ['warn', {
 | 
			
		||||
      switches: 'never',
 | 
			
		||||
    }],
 | 
			
		||||
    // Changed from 'as-needed' to 'consistent-as-needed'.
 | 
			
		||||
    'quote-props': ['error', 'consistent-as-needed'],
 | 
			
		||||
    // Disable in favour of TypeScript rule.
 | 
			
		||||
    'semi': 'off',
 | 
			
		||||
 | 
			
		||||
    // Import
 | 
			
		||||
 | 
			
		||||
    // Some packages have wrong type declarations.
 | 
			
		||||
    'import/default': 'off',
 | 
			
		||||
    'import/newline-after-import': 'warn',
 | 
			
		||||
    'import/no-absolute-path': 'error',
 | 
			
		||||
    // This rule disallows using both wildcard and selective imports from the same module.
 | 
			
		||||
    'import/no-duplicates': 'off',
 | 
			
		||||
    // Some packages have it wrong in type declarations (e.g. katex, marked).
 | 
			
		||||
    // Some packages has it wrong in type declarations (e.g. katex, marked).
 | 
			
		||||
    'import/no-named-as-default-member': 'off',
 | 
			
		||||
 | 
			
		||||
    // TypeScript
 | 
			
		||||
 | 
			
		||||
    // Changed options.
 | 
			
		||||
    '@typescript-eslint/ban-types': ['error', {
 | 
			
		||||
      // Allow to use {} and object - they are actually useful.
 | 
			
		||||
      types: {
 | 
			
		||||
        '{}': false,
 | 
			
		||||
        'object': false,
 | 
			
		||||
      },
 | 
			
		||||
      extendDefaults: true,
 | 
			
		||||
    }],
 | 
			
		||||
    '@typescript-eslint/class-literal-property-style': ['error', 'fields'],
 | 
			
		||||
    // Changed from error to off.
 | 
			
		||||
    '@typescript-eslint/consistent-type-definitions': 'off',
 | 
			
		||||
    // Changed from error to off.
 | 
			
		||||
    '@typescript-eslint/explicit-function-return-type': 'off',
 | 
			
		||||
    '@typescript-eslint/explicit-member-accessibility': ['error', {
 | 
			
		||||
    '@typescript-eslint/explicit-member-accessibility': ['warn', {
 | 
			
		||||
      accessibility: 'no-public',
 | 
			
		||||
      overrides: {
 | 
			
		||||
        parameterProperties: 'off',
 | 
			
		||||
      },
 | 
			
		||||
    }],
 | 
			
		||||
    // Changed from warn to error and adjusted options.
 | 
			
		||||
    '@typescript-eslint/explicit-module-boundary-types': ['error', {
 | 
			
		||||
      allowArgumentsExplicitlyTypedAsAny: true,
 | 
			
		||||
    }],
 | 
			
		||||
    '@typescript-eslint/func-call-spacing': ['error', 'never'],
 | 
			
		||||
    '@typescript-eslint/indent': ['error', 2, {
 | 
			
		||||
      SwitchCase: 1,
 | 
			
		||||
      VariableDeclarator: 1,
 | 
			
		||||
| 
						 | 
				
			
			@ -111,58 +95,31 @@ module.exports = {
 | 
			
		|||
      flatTernaryExpressions: true,
 | 
			
		||||
      ignoreComments: false,
 | 
			
		||||
    }],
 | 
			
		||||
    // Changed from error to warn.
 | 
			
		||||
    '@typescript-eslint/lines-between-class-members': 'warn',
 | 
			
		||||
    // Changed delimiter for type literals from none to comma.
 | 
			
		||||
    // The reason is just aesthetic symmetry with object literals.
 | 
			
		||||
    '@typescript-eslint/member-delimiter-style': ['error', {
 | 
			
		||||
      multiline: { delimiter: 'comma', requireLast: true },
 | 
			
		||||
      singleline: { delimiter: 'comma', requireLast: false },
 | 
			
		||||
      overrides: {
 | 
			
		||||
        interface: {
 | 
			
		||||
          multiline: { delimiter: 'none' },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    }],
 | 
			
		||||
    '@typescript-eslint/member-ordering': 'warn',
 | 
			
		||||
    // Changed from warn to off.
 | 
			
		||||
    '@typescript-eslint/no-explicit-any': 'off',
 | 
			
		||||
    // Changed from error to warn.
 | 
			
		||||
    '@typescript-eslint/no-extra-semi': 'warn',
 | 
			
		||||
    // It disallows using void even in valid cases.
 | 
			
		||||
    '@typescript-eslint/no-invalid-void-type': 'off',
 | 
			
		||||
    // Changed from error to warn.
 | 
			
		||||
    '@typescript-eslint/no-namespace': 'warn',
 | 
			
		||||
    // Changed from error to warn.
 | 
			
		||||
    '@typescript-eslint/no-non-null-assertion': 'warn',
 | 
			
		||||
    '@typescript-eslint/no-require-imports': 'error',
 | 
			
		||||
    // Changed from error to warn.
 | 
			
		||||
    '@typescript-eslint/no-unsafe-assignment': 'warn',
 | 
			
		||||
    // Changed from error to warn.
 | 
			
		||||
    '@typescript-eslint/no-unsafe-member-access': 'warn',
 | 
			
		||||
    // Disabled in favour of the next rule.
 | 
			
		||||
    '@typescript-eslint/no-unused-vars': 'off',
 | 
			
		||||
    '@typescript-eslint/no-unused-vars-experimental': 'error',
 | 
			
		||||
    // Changed options.
 | 
			
		||||
    '@typescript-eslint/no-unused-vars': ['error', {
 | 
			
		||||
      argsIgnorePattern: '^_',
 | 
			
		||||
    }],
 | 
			
		||||
    '@typescript-eslint/no-use-before-define': ['error', {
 | 
			
		||||
      classes: true,
 | 
			
		||||
      functions: false,
 | 
			
		||||
      typedefs: false,
 | 
			
		||||
      variables: true,
 | 
			
		||||
    }],
 | 
			
		||||
    '@typescript-eslint/prefer-for-of': 'warn',
 | 
			
		||||
    // Changed from error to warn.
 | 
			
		||||
    '@typescript-eslint/prefer-includes': 'warn',
 | 
			
		||||
    // Changed from error to warn.
 | 
			
		||||
    '@typescript-eslint/prefer-regexp-exec': 'warn',
 | 
			
		||||
    '@typescript-eslint/prefer-string-starts-ends-with': 'warn',
 | 
			
		||||
    // It has too many false positives.
 | 
			
		||||
    '@typescript-eslint/restrict-template-expressions': 'off',
 | 
			
		||||
    // Changed from error to off.
 | 
			
		||||
    '@typescript-eslint/strict-boolean-expressions': 'off',
 | 
			
		||||
    '@typescript-eslint/switch-exhaustiveness-check': 'error',
 | 
			
		||||
    // Changed from error to warn and adjusted options.
 | 
			
		||||
    '@typescript-eslint/unbound-method': ['warn', {
 | 
			
		||||
      ignoreStatic: true,
 | 
			
		||||
    '@typescript-eslint/promise-function-async': ['error', {
 | 
			
		||||
      allowAny: true,
 | 
			
		||||
    }],
 | 
			
		||||
    '@typescript-eslint/semi': ['error', 'never'],
 | 
			
		||||
    '@typescript-eslint/strict-boolean-expressions': 'off',
 | 
			
		||||
  },
 | 
			
		||||
  overrides: [
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -170,14 +127,7 @@ module.exports = {
 | 
			
		|||
      rules: {
 | 
			
		||||
        // Allow to format arrays for parametrized tests as tables.
 | 
			
		||||
        'array-bracket-spacing': 'off',
 | 
			
		||||
        'comma-dangle': ['error', {
 | 
			
		||||
          arrays: 'always-multiline',
 | 
			
		||||
          objects: 'always-multiline',
 | 
			
		||||
          imports: 'always-multiline',
 | 
			
		||||
          exports: 'always-multiline',
 | 
			
		||||
          // Changed to not require comma in a multiline expect().
 | 
			
		||||
          functions: 'only-multiline',
 | 
			
		||||
        }],
 | 
			
		||||
        'comma-spacing': 'off',
 | 
			
		||||
        'object-curly-spacing': 'off',
 | 
			
		||||
        'no-multi-spaces': 'off',
 | 
			
		||||
        'standard/array-bracket-even-spacing': 'off',
 | 
			
		||||
| 
						 | 
				
			
			@ -185,10 +135,7 @@ module.exports = {
 | 
			
		|||
        'space-in-parens': 'off',
 | 
			
		||||
        // jest.mock() must be above imports.
 | 
			
		||||
        'import/first': 'off',
 | 
			
		||||
        '@typescript-eslint/comma-spacing': 'off',
 | 
			
		||||
        // False positive on expect() functions.
 | 
			
		||||
        '@typescript-eslint/no-unsafe-call': 'off',
 | 
			
		||||
        '@typescript-eslint/no-unsafe-return': 'warn',
 | 
			
		||||
        '@typescript-eslint/no-non-null-assertion': 'off',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								.github/FUNDING.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/FUNDING.yml
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,3 +0,0 @@
 | 
			
		|||
# These are supported funding model platforms
 | 
			
		||||
 | 
			
		||||
github: jirutka
 | 
			
		||||
							
								
								
									
										68
									
								
								.github/workflows/ci.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										68
									
								
								.github/workflows/ci.yml
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,68 +0,0 @@
 | 
			
		|||
name: CI
 | 
			
		||||
on:
 | 
			
		||||
  - push
 | 
			
		||||
  - pull_request
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  test:
 | 
			
		||||
    name: Test on Node.js ${{ matrix.node-version }}
 | 
			
		||||
    runs-on: ubuntu-20.04
 | 
			
		||||
    strategy:
 | 
			
		||||
      matrix:
 | 
			
		||||
        node-version: [10, 12, 13, 14]
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v2
 | 
			
		||||
        with:
 | 
			
		||||
          fetch-depth: 0  # fetch all history to make `git describe` work
 | 
			
		||||
 | 
			
		||||
      - name: Setup Node.js ${{ matrix.node-version }}
 | 
			
		||||
        uses: actions/setup-node@v2
 | 
			
		||||
        with:
 | 
			
		||||
          node-version: ${{ matrix.node-version }}
 | 
			
		||||
 | 
			
		||||
      - run: yarn install
 | 
			
		||||
      - run: yarn build
 | 
			
		||||
      - run: yarn bundle
 | 
			
		||||
      - run: yarn test
 | 
			
		||||
      - run: yarn lint
 | 
			
		||||
 | 
			
		||||
  publish:
 | 
			
		||||
    name: Publish to npmjs and GitHub Releases
 | 
			
		||||
    needs: [test]
 | 
			
		||||
    if: startsWith(github.ref, 'refs/tags/v')
 | 
			
		||||
    runs-on: ubuntu-20.04
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v2
 | 
			
		||||
        with:
 | 
			
		||||
          fetch-depth: 0  # fetch all history to make `git describe` work
 | 
			
		||||
 | 
			
		||||
      - run: sudo apt-get install asciidoctor pandoc
 | 
			
		||||
 | 
			
		||||
      - uses: actions/setup-node@v2
 | 
			
		||||
        with:
 | 
			
		||||
          node-version: 14
 | 
			
		||||
          registry-url: https://registry.npmjs.org
 | 
			
		||||
 | 
			
		||||
      - run: yarn install
 | 
			
		||||
 | 
			
		||||
      - name: Generate source tarball
 | 
			
		||||
        run: ./scripts/create-src-tarball dist/ipynb2html-${GITHUB_REF/refs\/tags\//}-src.tar.gz
 | 
			
		||||
 | 
			
		||||
      - run: yarn build
 | 
			
		||||
      - run: yarn bundle
 | 
			
		||||
 | 
			
		||||
      - name: Publish packages to npmjs
 | 
			
		||||
        run: yarn publish-all --non-interactive
 | 
			
		||||
        env:
 | 
			
		||||
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
 | 
			
		||||
 | 
			
		||||
      - name: Upload tarballs to Releases
 | 
			
		||||
        uses: softprops/action-gh-release@v1
 | 
			
		||||
        env:
 | 
			
		||||
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        with:
 | 
			
		||||
          fail_on_unmatched_files: true
 | 
			
		||||
          files: |
 | 
			
		||||
            dist/*.tar.gz
 | 
			
		||||
            packages/ipynb2html-cli/dist/*.tar.gz
 | 
			
		||||
            packages/ipynb2html-cli/dist/*.zip
 | 
			
		||||
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -7,7 +7,6 @@
 | 
			
		|||
/.*cache/
 | 
			
		||||
/.tmp/
 | 
			
		||||
node_modules/
 | 
			
		||||
.eslintcache
 | 
			
		||||
.tsbuildinfo
 | 
			
		||||
tsconfig.tsbuildinfo
 | 
			
		||||
*.log
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										38
									
								
								.travis.yml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								.travis.yml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
dist: bionic
 | 
			
		||||
 | 
			
		||||
language: node_js
 | 
			
		||||
node_js:
 | 
			
		||||
  - '10'
 | 
			
		||||
  - '12'
 | 
			
		||||
  - node
 | 
			
		||||
 | 
			
		||||
addons:
 | 
			
		||||
  apt:
 | 
			
		||||
    packages:
 | 
			
		||||
      - asciidoctor
 | 
			
		||||
      - pandoc
 | 
			
		||||
 | 
			
		||||
env:
 | 
			
		||||
  global:
 | 
			
		||||
    - secure: "DrPA1eYBRjS+1/w/sRq/r5wQyOewuh1PGPzFtQR62TJeAyO6AvKQ6wfesxMA898b+0D3SCNxrCVK12XB3auySEOZocQuN7N51hsteA/QtPoBBbnoHy8Dap2YbiJ5fbCVnM/Wl/Z2rZmQWFBM3rmqXggCyEhKEw3kkz8WMm/7UCGVxmoHUelpMnDEII0RiJdPCGT19IA90KpJDsqbSzTVY+TsqjSNuN91LQ23ApwSHKklvbvKWxcgrtAzJDXLeS9CS3QqSHucurOM2Kpv0umOkBzds4da+NtWKYZC3XxThmMB5wT7b60EZPIc/iFftQFy2qiDAFxeGN+j9kwsNX68aXl4MuCGlzdvGj0KkeXYYhl1Jusc30uTzXYMlz2b3u+AcsMLLxFs2HvUU94SpAfe9VrarSnQK+6CZz0eCtF/NCCi6J9GqlBTsqzZDmdVaJpFDG1FidC4Ka9FcteKcWXqffowQ5KjIhqaearSmRESMqepV7T8tDUCb217PE0C+L0NGfg6RaY4DtGsJAawDeh/09aXrP6NakAKjWUfaJqjhkMexB8JTb+yanjVXsgj4VUfvTgvWjMi+yU3DIfopL+mawvgckRRL9DTEIf5ICjSruyEH8FWEz+kMzas41zboabR12YMLuorHfgZu31DiDsJkSD292t/lwWW6oybRl0iJBk="  # NPM_TOKEN=ceed......2bf2
 | 
			
		||||
 | 
			
		||||
cache: yarn
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
  - yarn install
 | 
			
		||||
 | 
			
		||||
script:
 | 
			
		||||
  - yarn run build
 | 
			
		||||
  - yarn run test
 | 
			
		||||
  - yarn run lint
 | 
			
		||||
 | 
			
		||||
before_deploy:
 | 
			
		||||
  - echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' >> "$HOME"/.npmrc
 | 
			
		||||
 | 
			
		||||
deploy:
 | 
			
		||||
  provider: script
 | 
			
		||||
  script: yarn publish-all --non-interactive
 | 
			
		||||
  skip_cleanup: true
 | 
			
		||||
  on:
 | 
			
		||||
    tags: true
 | 
			
		||||
    node_js: '10'
 | 
			
		||||
							
								
								
									
										2
									
								
								LICENSE
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								LICENSE
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
The MIT License
 | 
			
		||||
 | 
			
		||||
Copyright 2019-2020 Jakub Jirutka <jakub@jirutka.cz>.
 | 
			
		||||
Copyright 2019 Jakub Jirutka <jakub@jirutka.cz>.
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										55
									
								
								README.adoc
									
										
									
									
									
								
							
							
						
						
									
										55
									
								
								README.adoc
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2,15 +2,15 @@
 | 
			
		|||
:npm-name: ipynb2html
 | 
			
		||||
:gh-name: jirutka/{npm-name}
 | 
			
		||||
:gh-branch: master
 | 
			
		||||
:version: 0.3.0
 | 
			
		||||
:ansiup-version: 5.0.1
 | 
			
		||||
:hljs-version: 10.7.3
 | 
			
		||||
:katex-version: 0.13.11
 | 
			
		||||
:marked-version: 2.0.7
 | 
			
		||||
:version: 0.1.0-beta.7
 | 
			
		||||
:ansiup-version: 4.0.4
 | 
			
		||||
:hljs-version: 9.15.10
 | 
			
		||||
:katex-version: 0.11.1
 | 
			
		||||
:marked-version: 0.7.0
 | 
			
		||||
:vs-marketplace-uri: https://marketplace.visualstudio.com/items?itemName=
 | 
			
		||||
 | 
			
		||||
ifdef::env-github[]
 | 
			
		||||
image:https://github.com/{gh-name}/workflows/CI/badge.svg[CI Status, link=https://github.com/{gh-name}/actions?query=workflow%3A%22CI%22]
 | 
			
		||||
image:https://travis-ci.com/{gh-name}.svg?branch={gh-branch}[Build Status, link="https://travis-ci.com/{gh-name}"]
 | 
			
		||||
endif::env-github[]
 | 
			
		||||
 | 
			
		||||
{npm-name} is a converter (renderer) of the https://nbformat.readthedocs.io/en/stable/[Jupyter Notebook Format] 4.0+ to static HTML.
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +32,6 @@ endif::env-github[]
 | 
			
		|||
This package provides the converter itself and some utilities with *no dependencies*.
 | 
			
		||||
You have to provide your own syntax highlighter and Markdown, math and ANSI sequences renderer; or not, if you don’t need them.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=== {npm-name}
 | 
			
		||||
 | 
			
		||||
ifdef::env-github[]
 | 
			
		||||
| 
						 | 
				
			
			@ -47,49 +46,9 @@ This package builds on the {npm-name}-core and provides a complete, ready-to-go
 | 
			
		|||
* https://github.com/IonicaBizau/anser[anser] as ANSI sequences renderer,
 | 
			
		||||
* https://github.com/highlightjs/highlight.js[highlight.js] as syntax highlighter.
 | 
			
		||||
 | 
			
		||||
It also provides a reference stylesheet which you can find in `dist/notebook.min.css` (or non-minified link:packages/{npm-name}/styles/notebook.css[`styles/notebook.css`]).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=== {npm-name}-cli
 | 
			
		||||
 | 
			
		||||
ifdef::env-github[]
 | 
			
		||||
image:https://img.shields.io/npm/v/{npm-name}-cli.svg[Version on npm, link="https://www.npmjs.org/package/{npm-name}-cli"]
 | 
			
		||||
image:https://img.shields.io/bundlephobia/min/{npm-name}-cli.svg[Minified bundle size, link="https://bundlephobia.com/result?p={npm-name}-cli"]
 | 
			
		||||
endif::env-github[]
 | 
			
		||||
 | 
			
		||||
This package provides a CLI interface for {npm-name}.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ifndef::npm-readme[]
 | 
			
		||||
 | 
			
		||||
== Installation
 | 
			
		||||
 | 
			
		||||
All the <<Packages, packages>> can be installed using `npm` or `yarn` from https://www.npmjs.com/[npmjs.com].
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=== Standalone CLI Tool
 | 
			
		||||
 | 
			
		||||
{npm-name}-cli is also provided as a single minified JavaScript with all the external dependencies bundled in.
 | 
			
		||||
It requires only Node.js (version 10 or newer) to be installed on the system.
 | 
			
		||||
 | 
			
		||||
* https://github.com/{gh-name}/releases/download/v{version}/{npm-name}-cli-v{version}.tar.gz[{npm-name}-cli-v{version}.tar.gz]
 | 
			
		||||
* https://github.com/{gh-name}/releases/download/v{version}/{npm-name}-cli-v{version}.zip[{npm-name}-cli-v{version}.zip]
 | 
			
		||||
 | 
			
		||||
The archive also contains source maps (useful for debugging).
 | 
			
		||||
 | 
			
		||||
endif::[]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
== Usage
 | 
			
		||||
 | 
			
		||||
=== CLI
 | 
			
		||||
 | 
			
		||||
[source, subs="+attributes"]
 | 
			
		||||
{npm-name} notebook.ipynb notebook.html
 | 
			
		||||
 | 
			
		||||
Run `{npm-name} --help` for more information.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=== Node.js (server-side)
 | 
			
		||||
 | 
			
		||||
To render HTML in Node.js (server-side rendering), you need some (fake) DOM implementation.
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +91,6 @@ You can link it from https://www.jsdelivr.com/[jsDelivr CDN], for example:
 | 
			
		|||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
    <meta charset="utf-8">
 | 
			
		||||
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/{npm-name}@{version}/dist/notebook.min.css" crossorigin="anonymous">
 | 
			
		||||
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@{katex-version}/dist/katex.min.css" crossorigin="anonymous">
 | 
			
		||||
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@{hljs-version}/build/styles/default.min.css" crossorigin="anonymous">
 | 
			
		||||
    <script src="https://cdn.jsdelivr.net/npm/{npm-name}@{version}/dist/{npm-name}-full.min.js" crossorigin="anonymous"></script>
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +111,6 @@ document.body.appendChild(element)
 | 
			
		|||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
    <meta charset="utf-8">
 | 
			
		||||
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/{npm-name}@{version}/dist/notebook.min.css" crossorigin="anonymous">
 | 
			
		||||
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@{katex-version}/dist/katex.min.css" crossorigin="anonymous">
 | 
			
		||||
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@{hljs-version}/build/styles/default.min.css" crossorigin="anonymous">
 | 
			
		||||
    <script defer src="https://cdn.jsdelivr.net/npm/{npm-name}@{version}/dist/{npm-name}-full.min.js" crossorigin="anonymous"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,14 +4,17 @@
 | 
			
		|||
    <meta charset="utf-8" lang="cs">
 | 
			
		||||
    <meta name="viewport" content="initial-scale=1">
 | 
			
		||||
    <title>Example using ipynb2html-full.js</title>
 | 
			
		||||
    <link rel="stylesheet" href="../packages/ipynb2html/dist/notebook.min.css">
 | 
			
		||||
    <link
 | 
			
		||||
      rel="stylesheet"
 | 
			
		||||
      href="https://cdn.jsdelivr.net/npm/katex@0.13.11/dist/katex.min.css"
 | 
			
		||||
      href="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css"
 | 
			
		||||
      crossorigin="anonymous">
 | 
			
		||||
    <link
 | 
			
		||||
      rel="stylesheet"
 | 
			
		||||
      href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.7.3/build/styles/default.min.css"
 | 
			
		||||
      href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.15.10/build/styles/default.min.css"
 | 
			
		||||
      crossorigin="anonymous">
 | 
			
		||||
    <link
 | 
			
		||||
      rel="stylesheet"
 | 
			
		||||
      href="https://cdn.jsdelivr.net/gh/jsvine/nbpreview@c54381b/css/vendor/notebook.css"
 | 
			
		||||
      crossorigin="anonymous">
 | 
			
		||||
    <script defer src="../packages/ipynb2html/dist/ipynb2html-full.js" onload="ipynb2html.autoRender();"></script>
 | 
			
		||||
    <style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,19 +4,22 @@
 | 
			
		|||
    <meta charset="utf-8" lang="cs">
 | 
			
		||||
    <meta name="viewport" content="initial-scale=1">
 | 
			
		||||
    <title>Example using ipynb2html.js</title>
 | 
			
		||||
    <link rel="stylesheet" href="../packages/ipynb2html/dist/notebook.min.css">
 | 
			
		||||
    <link
 | 
			
		||||
      rel="stylesheet"
 | 
			
		||||
      href="https://cdn.jsdelivr.net/npm/katex@0.13.11/dist/katex.min.css"
 | 
			
		||||
      href="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css"
 | 
			
		||||
      crossorigin="anonymous">
 | 
			
		||||
    <link
 | 
			
		||||
      rel="stylesheet"
 | 
			
		||||
      href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.7.3/build/styles/default.min.css"
 | 
			
		||||
      href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.15.10/build/styles/default.min.css"
 | 
			
		||||
      crossorigin="anonymous">
 | 
			
		||||
    <script src="https://cdn.jsdelivr.net/npm/marked@2.0.7/marked.min.js" crossorigin="anonymous"></script>
 | 
			
		||||
    <script src="https://cdn.jsdelivr.net/npm/ansi_up@5.0.1/ansi_up.js" crossorigin="anonymous"></script>
 | 
			
		||||
    <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.7.3/build/highlight.min.js" crossorigin="anonymous"></script>
 | 
			
		||||
    <script src="https://cdn.jsdelivr.net/npm/katex@0.13.11/dist/katex.min.js" crossorigin="anonymous"></script>
 | 
			
		||||
    <link
 | 
			
		||||
      rel="stylesheet"
 | 
			
		||||
      href="https://cdn.jsdelivr.net/gh/jsvine/nbpreview@c54381b/css/vendor/notebook.css"
 | 
			
		||||
      crossorigin="anonymous">
 | 
			
		||||
    <script src="https://cdn.jsdelivr.net/npm/marked@0.7.0/marked.min.js" crossorigin="anonymous"></script>
 | 
			
		||||
    <script src="https://cdn.jsdelivr.net/npm/ansi_up@4.0.4/ansi_up.js" crossorigin="anonymous"></script>
 | 
			
		||||
    <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.15.10/build/highlight.min.js" crossorigin="anonymous"></script>
 | 
			
		||||
    <script src="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.js" crossorigin="anonymous"></script>
 | 
			
		||||
    <script defer src="../packages/ipynb2html/dist/ipynb2html.js" onload="ipynb2html.autoRender();"></script>
 | 
			
		||||
    <style>
 | 
			
		||||
      html, body {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,7 +63,7 @@ module.exports = {
 | 
			
		|||
  globals: {
 | 
			
		||||
    'ts-jest': {
 | 
			
		||||
      compiler: 'ttypescript',
 | 
			
		||||
      tsConfig: '<rootDir>/test/tsconfig.json',
 | 
			
		||||
      tsConfig: '<rootDir>/tsconfig.json',
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										78
									
								
								package.json
									
										
									
									
									
								
							
							
						
						
									
										78
									
								
								package.json
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,13 +1,13 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "ipynb2html-parent",
 | 
			
		||||
  "version": "0.3.0",
 | 
			
		||||
  "version": "0.1.0-beta.7",
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build": "ttsc --build",
 | 
			
		||||
    "bundle": "wsrun --exclude-missing bundle",
 | 
			
		||||
    "clean": "rimraf coverage/ dist/ lib/ .eslintcache *.log && wsrun clean",
 | 
			
		||||
    "lint": "eslint --cache --ext .ts,.tsx,.js .",
 | 
			
		||||
    "postinstall": "patch-package && run-s build",
 | 
			
		||||
    "clean": "rimraf coverage/ lib/ *.log && wsrun clean",
 | 
			
		||||
    "lint": "eslint --ext .ts,.tsx,.js .",
 | 
			
		||||
    "postinstall": "run-s build",
 | 
			
		||||
    "publish-all": "wsrun --serial publish",
 | 
			
		||||
    "test": "jest --detectOpenHandles --coverage --verbose",
 | 
			
		||||
    "version": "./scripts/bump-version && git add README.adoc **/package.json",
 | 
			
		||||
| 
						 | 
				
			
			@ -17,54 +17,48 @@
 | 
			
		|||
    "node": ">=10.13.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@babel/core": "^7.10.3",
 | 
			
		||||
    "@babel/preset-env": "^7.10.3",
 | 
			
		||||
    "@rollup/plugin-babel": "^5.0.3",
 | 
			
		||||
    "@rollup/plugin-commonjs": "^13.0.0",
 | 
			
		||||
    "@rollup/plugin-node-resolve": "^8.0.1",
 | 
			
		||||
    "@babel/core": "^7.6.3",
 | 
			
		||||
    "@babel/preset-env": "^7.6.3",
 | 
			
		||||
    "@types/dedent": "^0.7.0",
 | 
			
		||||
    "@types/jest": "^24.9.1",
 | 
			
		||||
    "@types/node": "^10.17.25",
 | 
			
		||||
    "@typescript-eslint/eslint-plugin": "^3.3.0",
 | 
			
		||||
    "@typescript-eslint/parser": "^3.3.0",
 | 
			
		||||
    "@types/highlightjs": "^9.12.0",
 | 
			
		||||
    "@types/jest": "^24.0.18",
 | 
			
		||||
    "@types/katex": "^0.10.2",
 | 
			
		||||
    "@types/marked": "^0.6.5",
 | 
			
		||||
    "@types/node": "^10.13.0",
 | 
			
		||||
    "@typescript-eslint/eslint-plugin": "^2.4.0",
 | 
			
		||||
    "@typescript-eslint/parser": "^2.4.0",
 | 
			
		||||
    "ansi_up": "^4.0.4",
 | 
			
		||||
    "arrify": "^2.0.1",
 | 
			
		||||
    "common-path-prefix": "^3.0.0",
 | 
			
		||||
    "core-js": "^3.6.5",
 | 
			
		||||
    "csso-cli": "^3.0.0",
 | 
			
		||||
    "core-js": "^3.2.1",
 | 
			
		||||
    "dedent": "^0.7.0",
 | 
			
		||||
    "eslint": "^7.3.0",
 | 
			
		||||
    "eslint-config-standard-with-typescript": "^18.0.2",
 | 
			
		||||
    "eslint-import-resolver-typescript": "^2.0.0",
 | 
			
		||||
    "eslint-plugin-import": "^2.21.2",
 | 
			
		||||
    "eslint-plugin-node": "^11.1.0",
 | 
			
		||||
    "eslint": "^6.5.1",
 | 
			
		||||
    "eslint-config-standard-with-typescript": "^10.0.0",
 | 
			
		||||
    "eslint-import-resolver-ts": "^0.4.0",
 | 
			
		||||
    "eslint-plugin-import": "^2.18.0",
 | 
			
		||||
    "eslint-plugin-node": "^10.0.0",
 | 
			
		||||
    "eslint-plugin-promise": "^4.2.1",
 | 
			
		||||
    "eslint-plugin-standard": "^4.0.0",
 | 
			
		||||
    "fs-extra": "^8.1.0",
 | 
			
		||||
    "jest": "^25.5.4",
 | 
			
		||||
    "jest-chain": "^1.1.5",
 | 
			
		||||
    "node-html-parser": "^1.2.19",
 | 
			
		||||
    "jest": "^24.9.0",
 | 
			
		||||
    "jest-chain": "^1.1.2",
 | 
			
		||||
    "nodom": "^2.3.0",
 | 
			
		||||
    "npm-run-all": "^4.1.5",
 | 
			
		||||
    "patch-package": "^6.2.2",
 | 
			
		||||
    "postinstall-postinstall": "^2.1.0",
 | 
			
		||||
    "rimraf": "^3.0.2",
 | 
			
		||||
    "rollup": "^2.17.1",
 | 
			
		||||
    "rollup-plugin-add-git-msg": "^1.1.0",
 | 
			
		||||
    "rollup-plugin-executable": "^1.6.0",
 | 
			
		||||
    "rollup-plugin-node-externals": "^2.2.0",
 | 
			
		||||
    "rollup-plugin-node-license": "^0.2.0",
 | 
			
		||||
    "rollup-plugin-terser": "^6.1.0",
 | 
			
		||||
    "rollup-plugin-typescript2": "^0.27.1",
 | 
			
		||||
    "tar": "^5.0.10",
 | 
			
		||||
    "ts-jest": "^25.5.1",
 | 
			
		||||
    "ts-node": "^8.10.2",
 | 
			
		||||
    "rimraf": "^3.0.0",
 | 
			
		||||
    "rollup": "^1.23.0",
 | 
			
		||||
    "rollup-plugin-add-git-msg": "^1.0.3",
 | 
			
		||||
    "rollup-plugin-babel": "^4.3.3",
 | 
			
		||||
    "rollup-plugin-commonjs": "^10.1.0",
 | 
			
		||||
    "rollup-plugin-node-resolve": "^5.2.0",
 | 
			
		||||
    "rollup-plugin-terser": "^5.1.2",
 | 
			
		||||
    "rollup-plugin-typescript2": "^0.24.3",
 | 
			
		||||
    "ts-jest": "^24.1.0",
 | 
			
		||||
    "ts-node": "^8.4.1",
 | 
			
		||||
    "ts-transformer-export-default-name": "^0.1.0",
 | 
			
		||||
    "ts-transformer-inline-file": "^0.1.1",
 | 
			
		||||
    "ttypescript": "^1.5.10",
 | 
			
		||||
    "typescript": "~3.9.5",
 | 
			
		||||
    "wsrun": "^5.2.1",
 | 
			
		||||
    "yarn-version-bump": "^0.0.3",
 | 
			
		||||
    "yazl": "^2.5.1"
 | 
			
		||||
    "ttypescript": "^1.5.7",
 | 
			
		||||
    "typescript": "~3.6.4",
 | 
			
		||||
    "wsrun": "^5.0.2",
 | 
			
		||||
    "yarn-version-bump": "^0.0.3"
 | 
			
		||||
  },
 | 
			
		||||
  "workspaces": [
 | 
			
		||||
    "packages/*"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
#!/usr/bin/env node
 | 
			
		||||
require('../lib/index').default(process.argv.slice(2))
 | 
			
		||||
| 
						 | 
				
			
			@ -1,54 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "ipynb2html-cli",
 | 
			
		||||
  "version": "0.3.0",
 | 
			
		||||
  "description": "CLI tool for converting Jupyter Notebooks to static HTML",
 | 
			
		||||
  "author": "Jakub Jirutka <jakub@jirutka.cz>",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "homepage": "https://github.com/jirutka/ipynb2html",
 | 
			
		||||
  "bugs": "https://github.com/jirutka/ipynb2html/issues",
 | 
			
		||||
  "repository": {
 | 
			
		||||
    "type": "git",
 | 
			
		||||
    "url": "https://github.com/jirutka/ipynb2html.git"
 | 
			
		||||
  },
 | 
			
		||||
  "keywords": [
 | 
			
		||||
    "cli",
 | 
			
		||||
    "converter",
 | 
			
		||||
    "html",
 | 
			
		||||
    "ipython",
 | 
			
		||||
    "jupyter",
 | 
			
		||||
    "notebook"
 | 
			
		||||
  ],
 | 
			
		||||
  "bin": {
 | 
			
		||||
    "ipynb2html": "bin/ipynb2html"
 | 
			
		||||
  },
 | 
			
		||||
  "main": "lib/index.js",
 | 
			
		||||
  "types": "lib/index.d.ts",
 | 
			
		||||
  "files": [
 | 
			
		||||
    "bin",
 | 
			
		||||
    "lib",
 | 
			
		||||
    "src"
 | 
			
		||||
  ],
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build": "ttsc --build",
 | 
			
		||||
    "bundle": "rollup -c && ./scripts/pack-bundle",
 | 
			
		||||
    "clean": "rimraf coverage/ dist/ lib/ .eslintcache .tsbuildinfo",
 | 
			
		||||
    "lint": "PKGDIR=$PWD; cd ../../ && eslint --cache --ext .ts,.tsx,.js $PKGDIR",
 | 
			
		||||
    "prepublishOnly": "run-s readme2md",
 | 
			
		||||
    "readme2md": "../../scripts/adoc2md -a npm-readme ../../README.adoc > README.md",
 | 
			
		||||
    "watch-ts": "ttsc --build --watch"
 | 
			
		||||
  },
 | 
			
		||||
  "engines": {
 | 
			
		||||
    "node": ">=10.13.0"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "ipynb2html": "0.3.0",
 | 
			
		||||
    "minimist": "^1.2.6",
 | 
			
		||||
    "minimist-options": "^4.0.2",
 | 
			
		||||
    "nodom": "^2.3.0",
 | 
			
		||||
    "source-map-support": "^0.5.16"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/minimist": "^1.2.0",
 | 
			
		||||
    "@types/source-map-support": "^0.5.1"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,67 +0,0 @@
 | 
			
		|||
import addGitMsg from 'rollup-plugin-add-git-msg'
 | 
			
		||||
import commonjs from '@rollup/plugin-commonjs'
 | 
			
		||||
import executable from 'rollup-plugin-executable'
 | 
			
		||||
import externals from 'rollup-plugin-node-externals'
 | 
			
		||||
import license from 'rollup-plugin-node-license'
 | 
			
		||||
import resolve from '@rollup/plugin-node-resolve'
 | 
			
		||||
import { terser } from 'rollup-plugin-terser'
 | 
			
		||||
import typescript from 'rollup-plugin-typescript2'
 | 
			
		||||
import ttypescript from 'ttypescript'
 | 
			
		||||
 | 
			
		||||
import pkg from './package.json'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  input: 'src/index.ts',
 | 
			
		||||
  plugins: [
 | 
			
		||||
    // Transpile TypeScript sources to JS.
 | 
			
		||||
    typescript({
 | 
			
		||||
      typescript: ttypescript,
 | 
			
		||||
      tsconfigOverride: {
 | 
			
		||||
        compilerOptions: {
 | 
			
		||||
          module: 'ESNext',
 | 
			
		||||
          declaration: false,
 | 
			
		||||
          declarationMap: false,
 | 
			
		||||
          composite: false,
 | 
			
		||||
          incremental: true,
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      clean: true,
 | 
			
		||||
    }),
 | 
			
		||||
    // Make node builtins external.
 | 
			
		||||
    externals(),
 | 
			
		||||
    // Resolve node modules.
 | 
			
		||||
    resolve({
 | 
			
		||||
      extensions: ['.mjs', '.js', '.ts'],
 | 
			
		||||
      mainFields: ['jsnext:main', 'module', 'main'],
 | 
			
		||||
    }),
 | 
			
		||||
    // Convert CommonJS modules to ES6 modules.
 | 
			
		||||
    commonjs(),
 | 
			
		||||
    // Add git tag, commit SHA and build date at top of the file.
 | 
			
		||||
    addGitMsg({
 | 
			
		||||
      copyright: [
 | 
			
		||||
        pkg.author,
 | 
			
		||||
        '* This project is licensed under the terms of the MIT license.'
 | 
			
		||||
      ].join('\n'),
 | 
			
		||||
    }),
 | 
			
		||||
    // Generate table of the bundled packages at top of the file.
 | 
			
		||||
    license({ format: 'table' }),
 | 
			
		||||
    // Minify JS.
 | 
			
		||||
    terser({
 | 
			
		||||
      ecma: 2018,
 | 
			
		||||
      output: {
 | 
			
		||||
      // Preserve comment injected by addGitMsg and license.
 | 
			
		||||
      comments: RegExp(`(?:\\$\\{${pkg.name}\\}|Bundled npm packages)`),
 | 
			
		||||
      },
 | 
			
		||||
    }),
 | 
			
		||||
    // Make the output file executable.
 | 
			
		||||
    executable(),
 | 
			
		||||
  ],
 | 
			
		||||
  output: {
 | 
			
		||||
    file: 'dist/ipynb2html',
 | 
			
		||||
    format: 'cjs',
 | 
			
		||||
    banner: '#!/usr/bin/env node',
 | 
			
		||||
    exports: 'named',
 | 
			
		||||
    sourcemap: true,
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +0,0 @@
 | 
			
		|||
#!/bin/sh
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
cd "$(dirname "$0")/../dist"
 | 
			
		||||
export PATH="$(pwd)/../../../scripts:$PATH"
 | 
			
		||||
 | 
			
		||||
assemble-license ipynb2html > LICENSE
 | 
			
		||||
create-archives ipynb2html-cli ipynb2html ipynb2html.map LICENSE
 | 
			
		||||
| 
						 | 
				
			
			@ -1,134 +0,0 @@
 | 
			
		|||
import fs from 'fs'
 | 
			
		||||
import minimist from 'minimist'
 | 
			
		||||
import minimistOptions from 'minimist-options'
 | 
			
		||||
import { Document } from 'nodom'
 | 
			
		||||
import { exit } from 'process'
 | 
			
		||||
import { $INLINE_FILE, $INLINE_JSON } from 'ts-transformer-inline-file'
 | 
			
		||||
 | 
			
		||||
import * as ipynb2html from 'ipynb2html'
 | 
			
		||||
 | 
			
		||||
import renderPage from './page'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
 | 
			
		||||
const { version, bugs: bugsUrl } = $INLINE_JSON('../package.json')
 | 
			
		||||
const notebookCss = $INLINE_FILE('../../ipynb2html/styles/notebook.css')
 | 
			
		||||
const pageCss = $INLINE_FILE('./page.css')
 | 
			
		||||
const progName = 'ipynb2html'
 | 
			
		||||
 | 
			
		||||
const helpMsg = `\
 | 
			
		||||
Usage: ${progName} [options] <input> [<output>]
 | 
			
		||||
 | 
			
		||||
Convert Jupyter Notebook 4.0+ to a static HTML page.
 | 
			
		||||
 | 
			
		||||
Arguments:
 | 
			
		||||
  <input>          Path of the Jupyter notebook to read, or "-" for STDIN.
 | 
			
		||||
  <output>         Path of the file to write the output HTML into. If not
 | 
			
		||||
                   provided, the output will be written to STDOUT.
 | 
			
		||||
 | 
			
		||||
Options:
 | 
			
		||||
  -d --debug             Print debug messages.
 | 
			
		||||
 | 
			
		||||
  -s --style <file,...>  Comma separated stylesheet(s) to embed into the output
 | 
			
		||||
                         HTML. The stylesheet may be a path to a CSS file,
 | 
			
		||||
                         "@base" for the base ipynb2html style, or "@default"
 | 
			
		||||
                         for the default full page style. Default is @default.
 | 
			
		||||
 | 
			
		||||
  -h --help              Show this message and exit.
 | 
			
		||||
 | 
			
		||||
  -V --version           Print version and exit.
 | 
			
		||||
 | 
			
		||||
Exit Codes:
 | 
			
		||||
  1                      Generic error code.
 | 
			
		||||
  2                      Missing required arguments or invalid option.
 | 
			
		||||
 | 
			
		||||
Please report bugs at <${bugsUrl}>.
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
function logErr (msg: string): void {
 | 
			
		||||
  console.error(`${progName}: ${msg}`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function arrify <T> (obj: T | T[]): T[] {
 | 
			
		||||
  return Array.isArray(obj) ? obj : [obj]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function parseCliArgs (argv: string[]) {
 | 
			
		||||
  const opts = minimist(argv, minimistOptions({
 | 
			
		||||
    debug: { alias: 'd', type: 'boolean' },
 | 
			
		||||
    style: { alias: 's', type: 'string', default: '@default' },
 | 
			
		||||
    version: { alias: 'V', type: 'boolean' },
 | 
			
		||||
    help: { alias: 'h', type: 'boolean' },
 | 
			
		||||
    arguments: 'string',
 | 
			
		||||
    stopEarly: true,
 | 
			
		||||
    unknown: (arg: string) => {
 | 
			
		||||
      if (arg.startsWith('-')) {
 | 
			
		||||
        logErr(`Unknown option: ${arg}`)
 | 
			
		||||
        return exit(2)
 | 
			
		||||
      } else {
 | 
			
		||||
        return true
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  }))
 | 
			
		||||
 | 
			
		||||
  if (opts.help) {
 | 
			
		||||
    console.log(helpMsg)
 | 
			
		||||
    return exit(0)
 | 
			
		||||
  }
 | 
			
		||||
  if (opts.version) {
 | 
			
		||||
    console.log(`${progName} ${version}`)
 | 
			
		||||
    return exit(0)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (opts._.length < 1 || opts._.length > 2) {
 | 
			
		||||
    logErr('Invalid number of arguments\n')
 | 
			
		||||
    console.log(helpMsg)
 | 
			
		||||
    return exit(2)
 | 
			
		||||
  }
 | 
			
		||||
  const [input, output] = opts._
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    styles: arrify(opts.style).join(',').split(/,\s*/),
 | 
			
		||||
    debug: opts.debug as boolean,
 | 
			
		||||
    input: input === '-' ? 0 : input,  // 0 = stdin
 | 
			
		||||
    output,
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function loadStyle (name: string): string {
 | 
			
		||||
  switch (name) {
 | 
			
		||||
    case '@base': return notebookCss
 | 
			
		||||
    case '@default': return pageCss + notebookCss
 | 
			
		||||
    default: return fs.readFileSync(name, 'utf8')
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default (argv: string[]): void => {
 | 
			
		||||
  const opts = parseCliArgs(argv)
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
 | 
			
		||||
    const notebook = JSON.parse(fs.readFileSync(opts.input, 'utf-8'))
 | 
			
		||||
    const style = opts.styles.map(loadStyle).join('\n')
 | 
			
		||||
 | 
			
		||||
    const title = ipynb2html.readNotebookTitle(notebook) || 'Notebook'
 | 
			
		||||
 | 
			
		||||
    const renderNotebook = ipynb2html.createRenderer(new Document())
 | 
			
		||||
    const contents = renderNotebook(notebook).outerHTML
 | 
			
		||||
 | 
			
		||||
    const html = renderPage({ contents, title, style })
 | 
			
		||||
 | 
			
		||||
    if (opts.output) {
 | 
			
		||||
      fs.writeFileSync(opts.output, html)
 | 
			
		||||
    } else {
 | 
			
		||||
      console.log(html)
 | 
			
		||||
    }
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    if (opts.debug) {
 | 
			
		||||
      console.debug(err)
 | 
			
		||||
    } else {
 | 
			
		||||
      logErr((err as Error).message)
 | 
			
		||||
    }
 | 
			
		||||
    return exit(1)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,15 +0,0 @@
 | 
			
		|||
import sourceMapSupport from 'source-map-support'
 | 
			
		||||
 | 
			
		||||
import cli from './cli'
 | 
			
		||||
 | 
			
		||||
// Allow to disable sourcemap when running from pkg bundle.
 | 
			
		||||
if (!/^(0|disable|false|no|off)$/i.test(process.env.NODE_SOURCEMAP ?? '')) {
 | 
			
		||||
  sourceMapSupport.install({ environment: 'node' })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// If the file is run directly (not required as a module), call CLI.
 | 
			
		||||
if (require.main === module) {
 | 
			
		||||
  cli(process.argv.slice(2))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default cli
 | 
			
		||||
| 
						 | 
				
			
			@ -1,95 +0,0 @@
 | 
			
		|||
html, body {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  background-color: #dedede;
 | 
			
		||||
  color: #2a2a2a;
 | 
			
		||||
  font-family: sans-serif;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
code,
 | 
			
		||||
pre {
 | 
			
		||||
  font-size: 0.85rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h1, h2, h3, h4, h5, h6 {
 | 
			
		||||
  margin-top: 1.6em;
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
h1 {
 | 
			
		||||
  font-size: 2em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h1 .anchor,
 | 
			
		||||
h2 .anchor,
 | 
			
		||||
h3 .anchor,
 | 
			
		||||
h4 .anchor,
 | 
			
		||||
h5 .anchor,
 | 
			
		||||
h6 .anchor {
 | 
			
		||||
  display: block;
 | 
			
		||||
  width: 1em;
 | 
			
		||||
  left: -1em;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h1:hover .anchor,
 | 
			
		||||
h2:hover .anchor,
 | 
			
		||||
h3:hover .anchor,
 | 
			
		||||
h4:hover .anchor,
 | 
			
		||||
h5:hover .anchor,
 | 
			
		||||
h6:hover .anchor {
 | 
			
		||||
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 50 50'%3E%3Cg fill='none' stroke='%23000' stroke-width='3'%3E%3Cpath d='M26.1 22a5.8 5.8 0 00-8.1 0l-9.6 9.5a5.8 5.8 0 008.2 8.2l5.8-5.9'/%3E%3Cpath d='M23.6 28a5.8 5.8 0 008.2 0l9.5-9.5a5.8 5.8 0 00-8.1-8.2l-5.8 5.9'/%3E%3C/g%3E%3C/svg%3E") no-repeat 100% center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table {
 | 
			
		||||
  border-collapse: collapse;
 | 
			
		||||
  border: 1px solid #cfcfcf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
th {
 | 
			
		||||
  font-weight: 600;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
td,
 | 
			
		||||
th {
 | 
			
		||||
  padding: 0.2em 0.4em;
 | 
			
		||||
  border: 1px solid #cfcfcf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
thead tr,
 | 
			
		||||
tbody tr:nth-child(even) {
 | 
			
		||||
  background-color: #f7f7f7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
thead tr:hover,
 | 
			
		||||
tbody tr:hover {
 | 
			
		||||
  background-color: #cfcfcf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-notebook {
 | 
			
		||||
  max-width: 45rem;
 | 
			
		||||
  margin: 1rem auto;
 | 
			
		||||
  padding: 3rem 6rem;
 | 
			
		||||
  background-color: white;
 | 
			
		||||
  box-shadow: 4px 4px 8px #cfcfcf, -4px -4px 8px #cfcfcf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-output table {
 | 
			
		||||
  font-size: 0.9em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (max-width: 900px) {
 | 
			
		||||
  .nb-notebook {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    padding-left: 5rem;
 | 
			
		||||
    padding-right: 3rem;
 | 
			
		||||
    max-width: none;
 | 
			
		||||
    box-shadow: none;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (max-width: 768px) {
 | 
			
		||||
  .nb-notebook {
 | 
			
		||||
    padding: 1rem 5% 2rem 5%;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,34 +0,0 @@
 | 
			
		|||
import { version } from 'ipynb2html'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export type Options = {
 | 
			
		||||
  contents: string,
 | 
			
		||||
  title: string,
 | 
			
		||||
  style: string,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default ({ contents, title, style }: Options): string => `\
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
    <meta charset="utf-8">
 | 
			
		||||
    <meta name="viewport" content="initial-scale=1">
 | 
			
		||||
    <meta name="generator" content="ipynb2html ${version}">
 | 
			
		||||
    <title>${title}</title>
 | 
			
		||||
    <link rel="stylesheet"
 | 
			
		||||
        href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.7.3/build/styles/default.min.css"
 | 
			
		||||
        integrity="sha384-s4RLYRjGGbVqKOyMGGwfxUTMOO6D7r2eom7hWZQ6BjK2Df4ZyfzLXEkonSm0KLIQ"
 | 
			
		||||
        crossorigin="anonymous">
 | 
			
		||||
    <link rel="stylesheet"
 | 
			
		||||
        href="https://cdn.jsdelivr.net/npm/katex@0.13.11/dist/katex.min.css"
 | 
			
		||||
        integrity="sha384-Um5gpz1odJg5Z4HAmzPtgZKdTBHZdw8S29IecapCSB31ligYPhHQZMIlWLYQGVoc"
 | 
			
		||||
        crossorigin="anonymous">
 | 
			
		||||
    <style>
 | 
			
		||||
${style.replace(/\n\n/g, '\n').replace(/\n$/, '').replace(/^/gm, '      ')}
 | 
			
		||||
    </style>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
${contents}
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
`
 | 
			
		||||
| 
						 | 
				
			
			@ -1,16 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "extends": "../../tsconfig.base.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "rootDir": "./src",
 | 
			
		||||
    "outDir": "./lib",
 | 
			
		||||
    "tsBuildInfoFile": "./.tsbuildinfo",
 | 
			
		||||
    "baseUrl": ".",
 | 
			
		||||
  },
 | 
			
		||||
  "include": [
 | 
			
		||||
    "./src",
 | 
			
		||||
  ],
 | 
			
		||||
  "references": [
 | 
			
		||||
    { "path": "../ipynb2html-core" },
 | 
			
		||||
    { "path": "../ipynb2html" },
 | 
			
		||||
  ],
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "ipynb2html-core",
 | 
			
		||||
  "version": "0.3.0",
 | 
			
		||||
  "version": "0.1.0-beta.7",
 | 
			
		||||
  "description": "Convert Jupyter Notebook to static HTML",
 | 
			
		||||
  "author": "Jakub Jirutka <jakub@jirutka.cz>",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
| 
						 | 
				
			
			@ -25,8 +25,8 @@
 | 
			
		|||
  ],
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build": "ttsc --build",
 | 
			
		||||
    "clean": "rimraf coverage/ lib/ .eslintcache .tsbuildinfo",
 | 
			
		||||
    "lint": "PKGDIR=$PWD; cd ../../ && eslint --cache --ext .ts,.tsx,.js $PKGDIR",
 | 
			
		||||
    "clean": "rimraf coverage/ lib/ .tsbuildinfo",
 | 
			
		||||
    "lint": "eslint --ext .ts,.tsx,.js .",
 | 
			
		||||
    "prepublishOnly": "run-s readme2md",
 | 
			
		||||
    "test": "jest --detectOpenHandles --coverage --verbose",
 | 
			
		||||
    "readme2md": "../../scripts/adoc2md -a npm-readme ../../README.adoc > README.md",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,8 +4,8 @@ type Attributes = { [k: string]: string }
 | 
			
		|||
// for this module's function.
 | 
			
		||||
export type MinimalElement = {
 | 
			
		||||
  innerHTML: string,
 | 
			
		||||
  setAttribute: (name: string, value: string) => void,
 | 
			
		||||
  appendChild: (child: any) => unknown,
 | 
			
		||||
  setAttribute (name: string, value: string): void,
 | 
			
		||||
  appendChild (child: any): any,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type ElementCreator<TElement = HTMLElement> =
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ export default <TElement> (opts: Options<TElement>): DataRenderer<TElement> => {
 | 
			
		|||
  const { elementCreator: el, mathRenderer: renderMath } = opts
 | 
			
		||||
 | 
			
		||||
  return (data: string): TElement => {
 | 
			
		||||
    const math = (extractMathRx.exec(data) ?? [])[1]
 | 
			
		||||
    const math = (extractMathRx.exec(data) || [])[1]
 | 
			
		||||
    return math
 | 
			
		||||
      ? el('div', ['latex-output'], renderMath(math))
 | 
			
		||||
      : el('div', ['html-output'], data)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,6 @@ import * as mathExtractor from './mathExtractor'
 | 
			
		|||
export { default as createElementCreator, ElementCreator, MinimalElement } from './elementCreator'
 | 
			
		||||
export { default as createHtmlRenderer } from './htmlRenderer'
 | 
			
		||||
export * from './nbformat'
 | 
			
		||||
export { default as NbRenderer, DataRenderer, NbRendererOpts } from './renderer'
 | 
			
		||||
export { default as createNbRenderer, DataRenderer, NbRenderer, Options as NbRendererOpts } from './renderer'
 | 
			
		||||
export { mathExtractor }
 | 
			
		||||
export { default as version } from './version'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,53 +1,36 @@
 | 
			
		|||
 | 
			
		||||
const htmlEntities: Record<string, string> = {
 | 
			
		||||
const htmlEntities = {
 | 
			
		||||
  '&': '&',
 | 
			
		||||
  '<': '<',
 | 
			
		||||
  '>': '>',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Callable = (...args: any[]) => any
 | 
			
		||||
/**
 | 
			
		||||
 * Creates a "callable object" with the given properties. In fact, it creates
 | 
			
		||||
 * a function that calls `obj[funcName]` and copies all the enumerable
 | 
			
		||||
 * properties of the *template* to the created function.
 | 
			
		||||
 *
 | 
			
		||||
 * @param {string} funcName Name of the function property of the *template*.
 | 
			
		||||
 * @param {Object} template The source object from which to copy enumerable properties.
 | 
			
		||||
 * @return A function with all enumerable properties of the *template*.
 | 
			
		||||
 */
 | 
			
		||||
export function callableObject <T, K extends keyof T> (
 | 
			
		||||
  funcName: K,
 | 
			
		||||
  template: T,
 | 
			
		||||
): T[K] extends Function ? T & T[K] : never {
 | 
			
		||||
 | 
			
		||||
type CallableConstructor = new <T> () => T extends { __call__: Callable }
 | 
			
		||||
  ? T['__call__']
 | 
			
		||||
  : 'subclass does not implement method __call__'
 | 
			
		||||
 | 
			
		||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment,
 | 
			
		||||
                  @typescript-eslint/no-unsafe-member-access,
 | 
			
		||||
                  @typescript-eslint/ban-types */
 | 
			
		||||
export const CallableInstance: CallableConstructor = function Callable (
 | 
			
		||||
  this: object,
 | 
			
		||||
): Callable {
 | 
			
		||||
 | 
			
		||||
  const func = this.constructor.prototype.__call__ as Callable
 | 
			
		||||
 | 
			
		||||
  const cls = function (...args: any[]) {
 | 
			
		||||
    return func.apply(cls, args) as unknown
 | 
			
		||||
  const fn = function (...args: any[]) {
 | 
			
		||||
    return (template[funcName] as any)(...args)
 | 
			
		||||
  }
 | 
			
		||||
  Object.setPrototypeOf(cls, this.constructor.prototype)
 | 
			
		||||
 | 
			
		||||
  Object.defineProperties(cls, {
 | 
			
		||||
    name: {
 | 
			
		||||
      value: this.constructor.name,
 | 
			
		||||
      configurable: true,
 | 
			
		||||
    },
 | 
			
		||||
    length: {
 | 
			
		||||
      value: func.length,
 | 
			
		||||
      configurable: true,
 | 
			
		||||
    },
 | 
			
		||||
  })
 | 
			
		||||
  return cls
 | 
			
		||||
} as any
 | 
			
		||||
CallableInstance.prototype = Object.create(Function.prototype)
 | 
			
		||||
/* eslint-enable @typescript-eslint/no-unsafe-assignment,
 | 
			
		||||
                 @typescript-eslint/no-unsafe-member-access,
 | 
			
		||||
                 @typescript-eslint/ban-types */
 | 
			
		||||
  return Object.assign(fn, template) as any
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Escapes characters with special meaning in HTML with the corresponding
 | 
			
		||||
 * HTML entities.
 | 
			
		||||
 */
 | 
			
		||||
export function escapeHTML (str: string): string {
 | 
			
		||||
  return str.replace(/[&<>]/g, c => htmlEntities[c])
 | 
			
		||||
  return str.replace(/[&<>]/g, c => (htmlEntities as any)[c])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -191,7 +191,7 @@ export function extractMath (text: string): [string, MathExpression[]] {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (lastIdx) {
 | 
			
		||||
    processMath(unescape, math, blocks, startIdx ?? 0, lastIdx)
 | 
			
		||||
    processMath(unescape, math, blocks, startIdx || 0, lastIdx)
 | 
			
		||||
    startIdx = endDelim = lastIdx = null
 | 
			
		||||
  }
 | 
			
		||||
  return [unescape(blocks.join('')), math.map(parseDelimitedMath)]
 | 
			
		||||
| 
						 | 
				
			
			@ -204,6 +204,6 @@ export function extractMath (text: string): [string, MathExpression[]] {
 | 
			
		|||
 */
 | 
			
		||||
export function restoreMath (text: string, math: string[]): string {
 | 
			
		||||
  return text
 | 
			
		||||
    .replace(/@@([1-9][0-9]*)@@/g, (_, n) => math[Number(n) - 1] ?? '')
 | 
			
		||||
    .replace(/@@([1-9][0-9]*)@@/g, (_, n) => math[Number(n) - 1])
 | 
			
		||||
    .replace(/@@0(\d+)@@/g, (_, n) => `@@${n}@@`)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,79 +1,78 @@
 | 
			
		|||
// These types are based on https://github.com/jupyter/nbformat/blob/b6b5a18e5a40d37f1cc0f71f65108288bdec9bb7/nbformat/v4/nbformat.v4.schema.json.
 | 
			
		||||
// This file was originally generated using json-schema-to-typescript 7.0.0 and
 | 
			
		||||
// then manually polished.
 | 
			
		||||
/* eslint-disable @typescript-eslint/member-ordering */
 | 
			
		||||
 | 
			
		||||
/** Jupyter Notebook v4.3. */
 | 
			
		||||
export interface Notebook {
 | 
			
		||||
 | 
			
		||||
  /** Notebook root-level metadata. */
 | 
			
		||||
  metadata: NotebookMetadata
 | 
			
		||||
  metadata: NotebookMetadata,
 | 
			
		||||
 | 
			
		||||
  /** Notebook format (minor number). Incremented for backward compatible changes to the notebook format. */
 | 
			
		||||
  nbformat_minor: number
 | 
			
		||||
  nbformat_minor: number,
 | 
			
		||||
 | 
			
		||||
  /** Notebook format (major number). Incremented between backwards incompatible changes to the notebook format. */
 | 
			
		||||
  nbformat: 4
 | 
			
		||||
  nbformat: 4,
 | 
			
		||||
 | 
			
		||||
  /** Array of cells of the current notebook. */
 | 
			
		||||
  cells: Cell[]
 | 
			
		||||
  cells: Cell[],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Notebook root-level metadata. */
 | 
			
		||||
export interface NotebookMetadata {
 | 
			
		||||
 | 
			
		||||
  /** Kernel information. */
 | 
			
		||||
  kernelspec?: KernelSpec
 | 
			
		||||
  kernelspec?: KernelSpec,
 | 
			
		||||
 | 
			
		||||
  /** Kernel information. */
 | 
			
		||||
  language_info?: LanguageInfo
 | 
			
		||||
  language_info?: LanguageInfo,
 | 
			
		||||
 | 
			
		||||
  /** Original notebook format (major number) before converting the notebook between versions. This should never be written to a file. */
 | 
			
		||||
  orig_nbformat?: number
 | 
			
		||||
  orig_nbformat?: number,
 | 
			
		||||
 | 
			
		||||
  /** The title of the notebook document */
 | 
			
		||||
  title?: string
 | 
			
		||||
  title?: string,
 | 
			
		||||
 | 
			
		||||
  /** The author(s) of the notebook document */
 | 
			
		||||
  authors?: any[]
 | 
			
		||||
  authors?: any[],
 | 
			
		||||
 | 
			
		||||
  /** Extra properties. */
 | 
			
		||||
  [key: string]: any
 | 
			
		||||
  [key: string]: any,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Kernel information. */
 | 
			
		||||
export interface KernelSpec {
 | 
			
		||||
 | 
			
		||||
  /** Name of the kernel specification. */
 | 
			
		||||
  name: string
 | 
			
		||||
  name: string,
 | 
			
		||||
 | 
			
		||||
  /** Name to display in UI. */
 | 
			
		||||
  display_name: string
 | 
			
		||||
  display_name: string,
 | 
			
		||||
 | 
			
		||||
  /** Extra properties. */
 | 
			
		||||
  [key: string]: any
 | 
			
		||||
  [key: string]: any,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Kernel information. */
 | 
			
		||||
export interface LanguageInfo {
 | 
			
		||||
 | 
			
		||||
  /** The programming language which this kernel runs. */
 | 
			
		||||
  name: string
 | 
			
		||||
  name: string,
 | 
			
		||||
 | 
			
		||||
  /** The codemirror mode to use for code in this language. */
 | 
			
		||||
  codemirror_mode?: string | { [k: string]: any }
 | 
			
		||||
  codemirror_mode?: string | { [k: string]: any },
 | 
			
		||||
 | 
			
		||||
  /** The file extension for files in this language. */
 | 
			
		||||
  file_extension?: string
 | 
			
		||||
  file_extension?: string,
 | 
			
		||||
 | 
			
		||||
  /** The mimetype corresponding to files in this language. */
 | 
			
		||||
  mimetype?: string
 | 
			
		||||
  mimetype?: string,
 | 
			
		||||
 | 
			
		||||
  /** The pygments lexer to use for code in this language. */
 | 
			
		||||
  pygments_lexer?: string
 | 
			
		||||
  pygments_lexer?: string,
 | 
			
		||||
 | 
			
		||||
  /** Extra properties. */
 | 
			
		||||
  [key: string]: any
 | 
			
		||||
  [key: string]: any,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -90,46 +89,46 @@ export enum CellType {
 | 
			
		|||
interface BaseCell {
 | 
			
		||||
 | 
			
		||||
  /** String identifying the type of cell. */
 | 
			
		||||
  cell_type: CellType
 | 
			
		||||
  cell_type: CellType,
 | 
			
		||||
 | 
			
		||||
  /** Cell-level metadata. */
 | 
			
		||||
  metadata: CellMetadata
 | 
			
		||||
  metadata: CellMetadata,
 | 
			
		||||
 | 
			
		||||
  /** Contents of the cell, represented as an array of lines. */
 | 
			
		||||
  source: MultilineString
 | 
			
		||||
  source: MultilineString,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Notebook raw nbconvert cell. */
 | 
			
		||||
export interface RawCell extends BaseCell {
 | 
			
		||||
 | 
			
		||||
  /** String identifying the type of cell. */
 | 
			
		||||
  cell_type: CellType.Raw
 | 
			
		||||
  cell_type: CellType.Raw,
 | 
			
		||||
 | 
			
		||||
  /** Cell-level metadata. */
 | 
			
		||||
  metadata: CellMetadata & {
 | 
			
		||||
    /** Raw cell metadata format for nbconvert. */
 | 
			
		||||
    format?: string,
 | 
			
		||||
  }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  /** Media attachments (e.g. inline images), stored as mimebundle keyed by filename. */
 | 
			
		||||
  attachments?: MediaAttachments
 | 
			
		||||
  attachments?: MediaAttachments,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Notebook markdown cell. */
 | 
			
		||||
export interface MarkdownCell extends BaseCell {
 | 
			
		||||
 | 
			
		||||
  /** String identifying the type of cell. */
 | 
			
		||||
  cell_type: CellType.Markdown
 | 
			
		||||
  cell_type: CellType.Markdown,
 | 
			
		||||
 | 
			
		||||
  /** Media attachments (e.g. inline images), stored as mimebundle keyed by filename. */
 | 
			
		||||
  attachments?: MediaAttachments
 | 
			
		||||
  attachments?: MediaAttachments,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Notebook code cell. */
 | 
			
		||||
export interface CodeCell extends BaseCell {
 | 
			
		||||
 | 
			
		||||
  /** String identifying the type of cell. */
 | 
			
		||||
  cell_type: CellType.Code
 | 
			
		||||
  cell_type: CellType.Code,
 | 
			
		||||
 | 
			
		||||
  /** Cell-level metadata. */
 | 
			
		||||
  metadata: CellMetadata & {
 | 
			
		||||
| 
						 | 
				
			
			@ -139,38 +138,38 @@ export interface CodeCell extends BaseCell {
 | 
			
		|||
 | 
			
		||||
    /** Whether the cell's output is scrolled, unscrolled, or autoscrolled. */
 | 
			
		||||
    scrolled?: true | false | 'auto',
 | 
			
		||||
  }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  /** Execution, display, or stream outputs. */
 | 
			
		||||
  outputs: Output[]
 | 
			
		||||
  outputs: Output[],
 | 
			
		||||
 | 
			
		||||
  /** The code cell's prompt number. Will be null if the cell has not been run. */
 | 
			
		||||
  execution_count: number | null
 | 
			
		||||
  execution_count: number | null,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface CellMetadata {
 | 
			
		||||
 | 
			
		||||
  /** Official Jupyter Metadata for Raw Cells */
 | 
			
		||||
  jupyter?: { [k: string]: any }
 | 
			
		||||
  jupyter?: { [k: string]: any },
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The cell's name. If present, must be a non-empty string. Cell names are expected to be unique
 | 
			
		||||
   * across all the cells in a given notebook. This criterion cannot be checked by the json schema
 | 
			
		||||
   * and must be established by an additional check.
 | 
			
		||||
   */
 | 
			
		||||
  name?: string
 | 
			
		||||
  name?: string,
 | 
			
		||||
 | 
			
		||||
  /** The cell's tags. Tags must be unique, and must not contain commas. */
 | 
			
		||||
  tags?: string[]
 | 
			
		||||
  tags?: string[],
 | 
			
		||||
 | 
			
		||||
  /** Extra properties. */
 | 
			
		||||
  [key: string]: any
 | 
			
		||||
  [key: string]: any,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface MediaAttachments {
 | 
			
		||||
 | 
			
		||||
  /** The attachment's data stored as a mimebundle. */
 | 
			
		||||
  [filename: string]: MimeBundle
 | 
			
		||||
  [filename: string]: MimeBundle,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -189,62 +188,62 @@ export enum OutputType {
 | 
			
		|||
export interface ExecuteResult {
 | 
			
		||||
 | 
			
		||||
  /** Type of cell output. */
 | 
			
		||||
  output_type: OutputType.ExecuteResult
 | 
			
		||||
  output_type: OutputType.ExecuteResult,
 | 
			
		||||
 | 
			
		||||
  /** A result's prompt number. */
 | 
			
		||||
  execution_count: number | null
 | 
			
		||||
  execution_count: number | null,
 | 
			
		||||
 | 
			
		||||
  /** A mime-type keyed dictionary of data */
 | 
			
		||||
  data: MimeBundle
 | 
			
		||||
  data: MimeBundle,
 | 
			
		||||
 | 
			
		||||
  /** Cell output metadata. */
 | 
			
		||||
  metadata: {
 | 
			
		||||
    [k: string]: any,
 | 
			
		||||
  }
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Data displayed as a result of code cell execution. */
 | 
			
		||||
export interface DisplayData {
 | 
			
		||||
 | 
			
		||||
  /** Type of cell output. */
 | 
			
		||||
  output_type: OutputType.DisplayData
 | 
			
		||||
  output_type: OutputType.DisplayData,
 | 
			
		||||
 | 
			
		||||
  /** A mime-type keyed dictionary of data */
 | 
			
		||||
  data: MimeBundle
 | 
			
		||||
  data: MimeBundle,
 | 
			
		||||
 | 
			
		||||
  /** Cell output metadata. */
 | 
			
		||||
  metadata: {
 | 
			
		||||
    [k: string]: any,
 | 
			
		||||
  }
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Stream output from a code cell. */
 | 
			
		||||
export interface StreamOutput {
 | 
			
		||||
 | 
			
		||||
  /** Type of cell output. */
 | 
			
		||||
  output_type: OutputType.Stream
 | 
			
		||||
  output_type: OutputType.Stream,
 | 
			
		||||
 | 
			
		||||
  /** The name of the stream (stdout, stderr). */
 | 
			
		||||
  name: string
 | 
			
		||||
  name: string,
 | 
			
		||||
 | 
			
		||||
  /** The stream's text output, represented as an array of strings. */
 | 
			
		||||
  text: MultilineString
 | 
			
		||||
  text: MultilineString,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Output of an error that occurred during code cell execution. */
 | 
			
		||||
export interface ErrorOutput {
 | 
			
		||||
 | 
			
		||||
  /** Type of cell output. */
 | 
			
		||||
  output_type: OutputType.Error
 | 
			
		||||
  output_type: OutputType.Error,
 | 
			
		||||
 | 
			
		||||
  /** The name of the error. */
 | 
			
		||||
  ename: string
 | 
			
		||||
  ename: string,
 | 
			
		||||
 | 
			
		||||
  /** The value, or message, of the error. */
 | 
			
		||||
  evalue: string
 | 
			
		||||
  evalue: string,
 | 
			
		||||
 | 
			
		||||
  /** The error's traceback, represented as an array of strings. */
 | 
			
		||||
  traceback: string[]
 | 
			
		||||
  traceback: string[],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -253,7 +252,7 @@ export interface ErrorOutput {
 | 
			
		|||
export interface MimeBundle {
 | 
			
		||||
 | 
			
		||||
  /** mimetype output (e.g. text/plain), represented as either an array of strings or a string. */
 | 
			
		||||
  [mediaType: string]: MultilineString
 | 
			
		||||
  [mediaType: string]: MultilineString,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type MultilineString = string | string[]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
// This code is originally based on notebookjs 0.4.2 distributed under the MIT license.
 | 
			
		||||
import { ElementCreator } from './elementCreator'
 | 
			
		||||
import { CallableInstance, escapeHTML, identity } from './internal/utils'
 | 
			
		||||
import { callableObject, escapeHTML, identity } from './internal/utils'
 | 
			
		||||
import {
 | 
			
		||||
  Cell,
 | 
			
		||||
  CellType,
 | 
			
		||||
| 
						 | 
				
			
			@ -17,18 +17,18 @@ import {
 | 
			
		|||
} from './nbformat'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export type NbRendererOpts<TElement = HTMLElement> = {
 | 
			
		||||
export type Options<TElement = HTMLElement> = {
 | 
			
		||||
  /**
 | 
			
		||||
   * An object with additional data renderers indexed by a media type.
 | 
			
		||||
   */
 | 
			
		||||
  dataRenderers?: DataRenderers<TElement>,
 | 
			
		||||
  /**
 | 
			
		||||
   * An array of the supported MIME types in the priority order. When a cell
 | 
			
		||||
   * An array of the supported media types in the priority order. When a cell
 | 
			
		||||
   * contains multiple representations of the data, the one with the media type
 | 
			
		||||
   * that has the lowest index in this array will be rendered. The default is
 | 
			
		||||
   * `Object.keys({ ...dataRenderers, ...builtinRenderers })`.
 | 
			
		||||
   */
 | 
			
		||||
  dataTypesPriority?: string[],
 | 
			
		||||
  dataRenderersOrder?: string[],
 | 
			
		||||
  /**
 | 
			
		||||
   * A function for converting ANSI escape sequences in the given *text* to HTML.
 | 
			
		||||
   * It gets the text from the cell as-is, without prior escaping, so it must
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ export type NbRendererOpts<TElement = HTMLElement> = {
 | 
			
		|||
  markdownRenderer?: (markup: string) => string,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type DataRenderer<TElement = HTMLElement> = (this: NbRenderer<TElement> | void, data: string) => TElement
 | 
			
		||||
export type DataRenderer<TElement = HTMLElement> = (data: string) => TElement
 | 
			
		||||
 | 
			
		||||
type DataRenderers<TElement> = { [mediaType: string]: DataRenderer<TElement> }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,173 +83,155 @@ function executionCountAttrs ({ execution_count: count }: CodeCell): { [k: strin
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
function notebookLanguage ({ metadata: meta }: Notebook): string {
 | 
			
		||||
  return meta.language_info?.name ?? 'python'
 | 
			
		||||
  return (meta.language_info && meta.language_info.name) || 'python'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class NbRenderer <TElement> extends CallableInstance<NbRenderer<TElement>> {
 | 
			
		||||
/**
 | 
			
		||||
 * Builds a Notebook renderer function with the given options. It returns a
 | 
			
		||||
 * "callable object" that exposes a renderer function for each of the
 | 
			
		||||
 * Notebook's AST node. You can easily replace any of the functions to modify
 | 
			
		||||
 * behaviour of the renderer.
 | 
			
		||||
 *
 | 
			
		||||
 * @param {ElementCreator} elementCreator The function that will be used for
 | 
			
		||||
 *   building all HTML elements.
 | 
			
		||||
 * @param {Options} opts
 | 
			
		||||
 * @return {NbRenderer}
 | 
			
		||||
 * @template TElement Type of the element object that *elementCreator* produces.
 | 
			
		||||
 */
 | 
			
		||||
function buildRenderer <TElement> (elementCreator: ElementCreator<TElement>, opts: Options<TElement> = {}) {
 | 
			
		||||
  const renderMarkdown = opts.markdownRenderer || identity
 | 
			
		||||
  const renderAnsiCodes = opts.ansiCodesRenderer || escapeHTML
 | 
			
		||||
  const highlightCode = opts.codeHighlighter || escapeHTML
 | 
			
		||||
 | 
			
		||||
  readonly el: ElementCreator<TElement>
 | 
			
		||||
  readonly renderMarkdown: NonNullable<NbRendererOpts['markdownRenderer']>
 | 
			
		||||
  readonly renderAnsiCodes: NonNullable<NbRendererOpts['ansiCodesRenderer']>
 | 
			
		||||
  readonly highlightCode: NonNullable<NbRendererOpts['codeHighlighter']>
 | 
			
		||||
  readonly dataRenderers: DataRenderers<TElement>
 | 
			
		||||
  readonly dataTypesPriority: string[]
 | 
			
		||||
  const el = elementCreator
 | 
			
		||||
  const el2 = (tag: string, classes: string[]) => (data: string) => el(tag, classes, data)
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Creates a Notebook renderer with the given options. The constructed object
 | 
			
		||||
   * is "callable", i.e. you can treat it as a function.
 | 
			
		||||
   *
 | 
			
		||||
   * @example
 | 
			
		||||
   *   const renderer = new NbRenderer(document.createElement.bind(document))
 | 
			
		||||
   *   console.log(renderer(notebook).outerHTML)
 | 
			
		||||
   *
 | 
			
		||||
   * @param {ElementCreator} elementCreator The function that will be used for
 | 
			
		||||
   *   building all HTML elements.
 | 
			
		||||
   * @param {NbRendererOpts} opts The renderer's options.
 | 
			
		||||
   */
 | 
			
		||||
  constructor (elementCreator: ElementCreator<TElement>, opts: NbRendererOpts<TElement> = {}) {
 | 
			
		||||
    super()
 | 
			
		||||
  const embeddedImageEl = (format: string) => (data: string) => el('img', {
 | 
			
		||||
    class: 'image-output',
 | 
			
		||||
    src: `data:image/${format};base64,${data.replace(/\n/g, '')}`,
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    this.el = elementCreator
 | 
			
		||||
    this.renderMarkdown = opts.markdownRenderer ?? identity
 | 
			
		||||
    this.renderAnsiCodes = opts.ansiCodesRenderer ?? escapeHTML
 | 
			
		||||
    this.highlightCode = opts.codeHighlighter ?? escapeHTML
 | 
			
		||||
  // opts.dataRenderers is intentionally included twice; to get the user's
 | 
			
		||||
  // provided renderers in the default dataRenderersOrder before the built-in
 | 
			
		||||
  // renderers and at the same time allow to override any built-in renderer.
 | 
			
		||||
  const dataRenderers: DataRenderers<TElement> = {
 | 
			
		||||
    ...opts.dataRenderers,
 | 
			
		||||
    'image/png': embeddedImageEl('png'),
 | 
			
		||||
    'image/jpeg': embeddedImageEl('jpeg'),
 | 
			
		||||
    'image/svg+xml': el2('div', ['svg-output']),
 | 
			
		||||
    'text/svg+xml': (data) => dataRenderers['image/svg+xml'](data),
 | 
			
		||||
    'text/html': el2('div', ['html-output']),
 | 
			
		||||
    'text/markdown': (data) => dataRenderers['text/html'](renderMarkdown(data)),
 | 
			
		||||
    'text/latex': el2('div', ['latex-output']),
 | 
			
		||||
    'application/javascript': el2('script', []),
 | 
			
		||||
    'text/plain': (data) => el('pre', ['text-output'], escapeHTML(data)),
 | 
			
		||||
    ...opts.dataRenderers,
 | 
			
		||||
  }
 | 
			
		||||
  const dataRenderersOrder = opts.dataRenderersOrder || Object.keys(dataRenderers)
 | 
			
		||||
 | 
			
		||||
    const el2 = (tag: string, classes: string[]) => (data: string) => this.el(tag, classes, data)
 | 
			
		||||
 | 
			
		||||
    const embeddedImageEl = (format: string) => (data: string) => this.el('img', {
 | 
			
		||||
      class: 'image-output',
 | 
			
		||||
      src: `data:image/${format};base64,${data.replace(/\n/g, '')}`,
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    // opts.dataRenderers is intentionally included twice; to get the user's
 | 
			
		||||
    // provided renderers in the default dataTypesPriority before the built-in
 | 
			
		||||
    // renderers and at the same time allow to override any built-in renderer.
 | 
			
		||||
    this.dataRenderers = {
 | 
			
		||||
      ...opts.dataRenderers,
 | 
			
		||||
      'image/png': embeddedImageEl('png'),
 | 
			
		||||
      'image/jpeg': embeddedImageEl('jpeg'),
 | 
			
		||||
      'image/svg+xml': el2('div', ['svg-output']),
 | 
			
		||||
      'text/svg+xml': (data) => this.dataRenderers['image/svg+xml'].call(this, data),
 | 
			
		||||
      'text/html': el2('div', ['html-output']),
 | 
			
		||||
      'text/markdown': (data) => this.el('div', ['html-output'], this.renderMarkdown(data)),
 | 
			
		||||
      'text/latex': el2('div', ['latex-output']),
 | 
			
		||||
      'application/javascript': el2('script', []),
 | 
			
		||||
      'text/plain': (data) => this.el('pre', ['text-output'], escapeHTML(data)),
 | 
			
		||||
      ...opts.dataRenderers,
 | 
			
		||||
    }
 | 
			
		||||
    this.dataTypesPriority = opts.dataTypesPriority ?? Object.keys(this.dataRenderers)
 | 
			
		||||
  const resolveDataType = (output: DisplayData | ExecuteResult) => {
 | 
			
		||||
    return dataRenderersOrder.find(type => output.data[type] && dataRenderers[type])
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Renders the given Jupyter *notebook*.
 | 
			
		||||
   */
 | 
			
		||||
  __call__ (notebook: Notebook): TElement {
 | 
			
		||||
    return this.render(notebook)
 | 
			
		||||
  }
 | 
			
		||||
  const r = callableObject('Notebook', {
 | 
			
		||||
    Notebook: (notebook: Notebook): TElement => {
 | 
			
		||||
      const children = notebook.cells.map(cell => r.Cell(cell, notebook))
 | 
			
		||||
      // Class "worksheet" is for backward compatibility with notebook.js.
 | 
			
		||||
      return el('div', ['notebook', 'worksheet'], children)
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Renders the given Jupyter *notebook*.
 | 
			
		||||
   */
 | 
			
		||||
  render (notebook: Notebook): TElement {
 | 
			
		||||
    const children = notebook.cells.map(cell => this.renderCell(cell, notebook))
 | 
			
		||||
    return this.el('div', ['notebook'], children)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  renderCell (cell: Cell, notebook: Notebook): TElement {
 | 
			
		||||
    switch (cell.cell_type) {
 | 
			
		||||
      case CellType.Code: return this.renderCodeCell(cell, notebook)
 | 
			
		||||
      case CellType.Markdown: return this.renderMarkdownCell(cell, notebook)
 | 
			
		||||
      case CellType.Raw: return this.renderRawCell(cell, notebook)
 | 
			
		||||
      default: return this.el('div', [], '<!-- Unsupported cell type -->')
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  renderMarkdownCell (cell: MarkdownCell, _notebook: Notebook): TElement {
 | 
			
		||||
    return this.el('section', ['cell', 'markdown-cell'], this.renderMarkdown(joinText(cell.source)))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  renderRawCell (cell: RawCell, _notebook: Notebook): TElement {
 | 
			
		||||
    return this.el('section', ['cell', 'raw-cell'], joinText(cell.source))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  renderCodeCell (cell: CodeCell, notebook: Notebook): TElement {
 | 
			
		||||
    const source = cell.source.length > 0
 | 
			
		||||
      ? this.renderSource(cell, notebook)
 | 
			
		||||
      : this.el('div')
 | 
			
		||||
 | 
			
		||||
    const outputs = coalesceStreams(cell.outputs ?? [])
 | 
			
		||||
      .map(output => this.renderOutput(output, cell))
 | 
			
		||||
 | 
			
		||||
    return this.el('section', ['cell', 'code-cell'], [source, ...outputs])
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  renderSource (cell: CodeCell, notebook: Notebook): TElement {
 | 
			
		||||
    const lang = notebookLanguage(notebook)
 | 
			
		||||
    const html = this.highlightCode(joinText(cell.source), lang)
 | 
			
		||||
 | 
			
		||||
    const codeEl = this.el('code', { 'class': `lang-${lang}`, 'data-language': lang }, html)
 | 
			
		||||
    const preEl = this.el('pre', [], [codeEl])
 | 
			
		||||
 | 
			
		||||
    // Class "input" is for backward compatibility with notebook.js.
 | 
			
		||||
    const attrs = { ...executionCountAttrs(cell), class: 'source input' }
 | 
			
		||||
 | 
			
		||||
    return this.el('div', attrs, [preEl])
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  renderOutput (output: Output, cell: CodeCell): TElement {
 | 
			
		||||
    const innerEl = (() => {
 | 
			
		||||
      switch (output.output_type) {
 | 
			
		||||
        case OutputType.DisplayData: return this.renderDisplayData(output)
 | 
			
		||||
        case OutputType.ExecuteResult: return this.renderExecuteResult(output)
 | 
			
		||||
        case OutputType.Stream: return this.renderStream(output)
 | 
			
		||||
        case OutputType.Error: return this.renderError(output)
 | 
			
		||||
        default: return this.el('div', [], '<!-- Unsupported output type -->')
 | 
			
		||||
    Cell: (cell: Cell, notebook: Notebook): TElement => {
 | 
			
		||||
      switch (cell.cell_type) {
 | 
			
		||||
        case CellType.Code: return r.CodeCell(cell, notebook)
 | 
			
		||||
        case CellType.Markdown: return r.MarkdownCell(cell, notebook)
 | 
			
		||||
        case CellType.Raw: return r.RawCell(cell, notebook)
 | 
			
		||||
        default: return el('div', [], '<!-- Unsupported cell type -->')
 | 
			
		||||
      }
 | 
			
		||||
    })()
 | 
			
		||||
    const attrs = { ...executionCountAttrs(cell), class: 'output' }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    return this.el('div', attrs, [innerEl])
 | 
			
		||||
  }
 | 
			
		||||
    MarkdownCell: (cell: MarkdownCell, _notebook: Notebook): TElement => {
 | 
			
		||||
      return el('div', ['cell', 'markdown-cell'], renderMarkdown(joinText(cell.source)))
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
  renderDisplayData (output: DisplayData): TElement {
 | 
			
		||||
    const type = this.resolveDataType(output)
 | 
			
		||||
    if (type) {
 | 
			
		||||
      return this.renderData(type, joinText(output.data[type]))
 | 
			
		||||
    }
 | 
			
		||||
    return this.el('div', ['empty-output'])
 | 
			
		||||
  }
 | 
			
		||||
    RawCell: (cell: RawCell, _notebook: Notebook): TElement => {
 | 
			
		||||
      return el('div', ['cell', 'raw-cell'], joinText(cell.source))
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
  renderExecuteResult (output: ExecuteResult): TElement {
 | 
			
		||||
    const type = this.resolveDataType(output)
 | 
			
		||||
    if (type) {
 | 
			
		||||
      return this.renderData(type, joinText(output.data[type]))
 | 
			
		||||
    }
 | 
			
		||||
    return this.el('div', ['empty-output'])
 | 
			
		||||
  }
 | 
			
		||||
    CodeCell: (cell: CodeCell, notebook: Notebook): TElement => {
 | 
			
		||||
      const source = cell.source.length > 0
 | 
			
		||||
        ? r.Source(cell, notebook)
 | 
			
		||||
        : el('div')
 | 
			
		||||
 | 
			
		||||
  renderError (error: ErrorOutput): TElement {
 | 
			
		||||
    const html = this.renderAnsiCodes(error.traceback.join('\n'))
 | 
			
		||||
    // Class "pyerr" is for backward compatibility with notebook.js.
 | 
			
		||||
    return this.el('pre', ['error', 'pyerr'], html)
 | 
			
		||||
  }
 | 
			
		||||
      const outputs = coalesceStreams(cell.outputs || [])
 | 
			
		||||
        .map(output => r.Output(output, cell))
 | 
			
		||||
 | 
			
		||||
  renderStream (stream: StreamOutput): TElement {
 | 
			
		||||
    const html = this.renderAnsiCodes(joinText(stream.text))
 | 
			
		||||
    return this.el('pre', [stream.name], html)
 | 
			
		||||
  }
 | 
			
		||||
      return el('div', ['cell', 'code-cell'], [source, ...outputs])
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
  renderData (mimeType: string, data: string): TElement {
 | 
			
		||||
    const render = this.dataRenderers[mimeType]
 | 
			
		||||
    if (!render) {
 | 
			
		||||
      throw RangeError(`missing renderer for MIME type: ${mimeType}`)
 | 
			
		||||
    }
 | 
			
		||||
    return render.call(this, data)
 | 
			
		||||
  }
 | 
			
		||||
    Source: (cell: CodeCell, notebook: Notebook): TElement => {
 | 
			
		||||
      const lang = notebookLanguage(notebook)
 | 
			
		||||
      const html = highlightCode(joinText(cell.source), lang)
 | 
			
		||||
 | 
			
		||||
  resolveDataType (output: DisplayData | ExecuteResult): string | undefined {
 | 
			
		||||
    return this.dataTypesPriority.find(type => output.data[type])
 | 
			
		||||
  }
 | 
			
		||||
      const codeEl = el('code', { 'class': `lang-${lang}`, 'data-language': lang }, html)
 | 
			
		||||
      const preEl = el('pre', [], [codeEl])
 | 
			
		||||
 | 
			
		||||
      // Class "input" is for backward compatibility with notebook.js.
 | 
			
		||||
      const attrs = { ...executionCountAttrs(cell), class: 'source input' }
 | 
			
		||||
 | 
			
		||||
      return el('div', attrs, [preEl])
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    Output: (output: Output, cell: CodeCell): TElement => {
 | 
			
		||||
      const innerEl = (() => {
 | 
			
		||||
        switch (output.output_type) {
 | 
			
		||||
          case OutputType.DisplayData: return r.DisplayData(output)
 | 
			
		||||
          case OutputType.ExecuteResult: return r.ExecuteResult(output)
 | 
			
		||||
          case OutputType.Stream: return r.Stream(output)
 | 
			
		||||
          case OutputType.Error: return r.Error(output)
 | 
			
		||||
          default: return el('div', [], '<!-- Unsupported output type -->')
 | 
			
		||||
        }
 | 
			
		||||
      })()
 | 
			
		||||
      const attrs = { ...executionCountAttrs(cell), class: 'output' }
 | 
			
		||||
 | 
			
		||||
      return el('div', attrs, [innerEl])
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    DisplayData: (output: DisplayData): TElement => {
 | 
			
		||||
      const type = resolveDataType(output)
 | 
			
		||||
      if (type) {
 | 
			
		||||
        return dataRenderers[type](joinText(output.data[type]))
 | 
			
		||||
      }
 | 
			
		||||
      return el('div', ['empty-output'])
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    ExecuteResult: (output: ExecuteResult): TElement => {
 | 
			
		||||
      const type = resolveDataType(output)
 | 
			
		||||
      if (type) {
 | 
			
		||||
        return dataRenderers[type](joinText(output.data[type]))
 | 
			
		||||
      }
 | 
			
		||||
      return el('div', ['empty-output'])
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    Error: (error: ErrorOutput): TElement => {
 | 
			
		||||
      const html = renderAnsiCodes(error.traceback.join('\n'))
 | 
			
		||||
      // Class "pyerr" is for backward compatibility with notebook.js.
 | 
			
		||||
      return el('pre', ['error', 'pyerr'], html)
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    Stream: (stream: StreamOutput): TElement => {
 | 
			
		||||
      const html = renderAnsiCodes(joinText(stream.text))
 | 
			
		||||
      return el('pre', [stream.name], html)
 | 
			
		||||
    },
 | 
			
		||||
  })
 | 
			
		||||
  return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default NbRenderer
 | 
			
		||||
export default buildRenderer
 | 
			
		||||
 | 
			
		||||
// XXX: An ugly hack to infer return type of generic function that returns
 | 
			
		||||
// generalized object.
 | 
			
		||||
abstract class DummyClass<T> {
 | 
			
		||||
  renderer = buildRenderer<T>(this.elementCreator())
 | 
			
		||||
  abstract elementCreator (): ElementCreator<T>
 | 
			
		||||
}
 | 
			
		||||
export type NbRenderer<TElement> = DummyClass<TElement>['renderer']
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
import { $INLINE_JSON } from 'ts-transformer-inline-file'
 | 
			
		||||
 | 
			
		||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
 | 
			
		||||
const { version } = $INLINE_JSON('../package.json')
 | 
			
		||||
 | 
			
		||||
export default version as string
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,64 +1,31 @@
 | 
			
		|||
import { CallableInstance, escapeHTML, identity } from '@/internal/utils'
 | 
			
		||||
import { callableObject, escapeHTML, identity } from '@/internal/utils'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
describe('CallableInstance', () => {
 | 
			
		||||
describe('.callableObject', () => {
 | 
			
		||||
 | 
			
		||||
  class FixtureCallable extends CallableInstance<FixtureCallable> {
 | 
			
		||||
    readonly salutation: string
 | 
			
		||||
 | 
			
		||||
    constructor (salutation: string) {
 | 
			
		||||
      super()
 | 
			
		||||
      this.salutation = salutation
 | 
			
		||||
  describe('returned value', () => {
 | 
			
		||||
    const template = {
 | 
			
		||||
      str: 'allons-y!',
 | 
			
		||||
      func1: jest.fn().mockReturnValue(1),
 | 
			
		||||
      func2: jest.fn().mockReturnValue(2),
 | 
			
		||||
    }
 | 
			
		||||
    const subject = callableObject('func1', template)
 | 
			
		||||
 | 
			
		||||
    __call__ (name: string) {
 | 
			
		||||
      return this.salute(name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    salute (name: string) {
 | 
			
		||||
      return `${this.salutation}, ${name}!`
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  describe('subclass', () => {
 | 
			
		||||
    it('can be instantiated using new', () => {
 | 
			
		||||
      expect(() => new FixtureCallable('Hello') ).not.toThrow()
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('subclass instance', () => {
 | 
			
		||||
    let instance: FixtureCallable
 | 
			
		||||
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
      instance = new FixtureCallable('Hello')
 | 
			
		||||
    it('is a function that calls the specified template function', () => {
 | 
			
		||||
      expect( subject ).toBeInstanceOf(Function)
 | 
			
		||||
      expect( subject('a', 'b') ).toBe(1)
 | 
			
		||||
      expect( template.func1 ).toBeCalledWith('a', 'b')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('is an instance of its class', () => {
 | 
			
		||||
      expect( instance ).toBeInstanceOf(FixtureCallable)
 | 
			
		||||
      expect( instance.salutation ).toBe('Hello')
 | 
			
		||||
      expect( instance.salute('world') ).toBe('Hello, world!')
 | 
			
		||||
    it('is not the same function as the specified template function', () => {
 | 
			
		||||
      expect( subject ).not.toBe(template.func1)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('is an instance of Function', () => {
 | 
			
		||||
      expect( instance ).toBeInstanceOf(Function)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('is a typeof function', () => {
 | 
			
		||||
      expect( typeof instance ).toBe('function')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('has function property "name" that equals the class name', () => {
 | 
			
		||||
      expect( instance.name ).toBe('FixtureCallable')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('has function property "length" that equals number of arguments of the __call__ method', () => {
 | 
			
		||||
      expect( instance.length ).toBe(1)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('can be called, redirects to the method __call__', () => {
 | 
			
		||||
      expect( instance('world') ).toBe('Hello, world!')
 | 
			
		||||
      expect( instance.apply(null, ['world']) ).toBe('Hello, world!')  // eslint-disable-line no-useless-call
 | 
			
		||||
      expect( instance.call(null, 'world') ).toBe('Hello, world!')  // eslint-disable-line no-useless-call
 | 
			
		||||
    it('has all enumerable properties of the given template', () => {
 | 
			
		||||
      expect( subject )
 | 
			
		||||
        .toHaveProperty('str', template.str)
 | 
			
		||||
        .toHaveProperty('func1', template.func1)
 | 
			
		||||
        .toHaveProperty('func2', template.func2)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ describe('.extractMath', () => {
 | 
			
		|||
 | 
			
		||||
        it('extracts and substitutes math expression in the given text', () => {
 | 
			
		||||
          expect(
 | 
			
		||||
            extractMath(`Let's define ${raw}.`),
 | 
			
		||||
            extractMath(`Let's define ${raw}.`)
 | 
			
		||||
          ).toEqual(["Let's define @@1@@.", [{ displayMode, raw, value }]])
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ describe('.extractMath', () => {
 | 
			
		|||
 | 
			
		||||
        it('extracts and substitutes math expression in the given text', () => {
 | 
			
		||||
          expect(
 | 
			
		||||
            extractMath(`Let's define ${raw}.`),
 | 
			
		||||
            extractMath(`Let's define ${raw}.`)
 | 
			
		||||
          ).toEqual(["Let's define @@1@@.", [{ displayMode, raw, value }]])
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ describe('.extractMath', () => {
 | 
			
		|||
 | 
			
		||||
    it('extracts and substitutes math expression in the given text', () => {
 | 
			
		||||
      expect(
 | 
			
		||||
        extractMath(`Let's define ${raw}.`),
 | 
			
		||||
        extractMath(`Let's define ${raw}.`)
 | 
			
		||||
      ).toEqual(["Let's define @@1@@.", [{ displayMode: true, raw, value: raw }]])
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
| 
						 | 
				
			
			@ -52,14 +52,14 @@ describe('.extractMath', () => {
 | 
			
		|||
 | 
			
		||||
    it('escapes @@[0-9]+@@ as @@0[0-9]+@@', () => {
 | 
			
		||||
      expect(
 | 
			
		||||
        extractMath('This @@02@@ is not our marker'),
 | 
			
		||||
        extractMath('This @@02@@ is not our marker')
 | 
			
		||||
      ).toEqual(['This @@002@@ is not our marker', []])
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('ignores math delimiters inside `inline code`', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
      extractMath('`$x$` and ``$`x`$`` is a code, $x$ is not'),
 | 
			
		||||
      extractMath('`$x$` and ``$`x`$`` is a code, $x$ is not')
 | 
			
		||||
    ).toEqual([
 | 
			
		||||
      '`$x$` and ``$`x`$`` is a code, @@1@@ is not',
 | 
			
		||||
      [{ displayMode: false, raw: '$x$', value: 'x' }],
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +68,7 @@ describe('.extractMath', () => {
 | 
			
		|||
 | 
			
		||||
  it('ignores math delimiters inside `inline code` with line breaks', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
      extractMath('`$x\n$` and ``\n$`x`$\n`` is a code, `$x$\n\nis` not'),
 | 
			
		||||
      extractMath('`$x\n$` and ``\n$`x`$\n`` is a code, `$x$\n\nis` not')
 | 
			
		||||
    ).toEqual([
 | 
			
		||||
      '`$x\n$` and ``\n$`x`$\n`` is a code, `@@1@@\n\nis` not',
 | 
			
		||||
      [{ displayMode: false, raw: '$x$', value: 'x' }],
 | 
			
		||||
| 
						 | 
				
			
			@ -135,13 +135,13 @@ describe('.restoreMath', () => {
 | 
			
		|||
    repl[21] = 'second'
 | 
			
		||||
 | 
			
		||||
    expect(
 | 
			
		||||
      restoreMath("Let's define @@1@@ and @@22@@.", repl),
 | 
			
		||||
      restoreMath("Let's define @@1@@ and @@22@@.", repl)
 | 
			
		||||
    ).toEqual("Let's define first and second.")
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('unescapes marker-like sequences', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
      restoreMath('This @@001@@ is not our marker, nor @@01@@, but @@1@@ is.', ['this one']),
 | 
			
		||||
      restoreMath('This @@001@@ is not our marker, nor @@01@@, but @@1@@ is.', ['this one'])
 | 
			
		||||
    ).toEqual('This @@01@@ is not our marker, nor @@1@@, but this one is.')
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,20 +1,19 @@
 | 
			
		|||
/* eslint-disable @typescript-eslint/unbound-method */
 | 
			
		||||
 | 
			
		||||
import '~/test/setup'  // setupFilesAfterEnv doesn't work here
 | 
			
		||||
 | 
			
		||||
import arrify from 'arrify'
 | 
			
		||||
import { Document, HTMLElement } from 'nodom'
 | 
			
		||||
 | 
			
		||||
import buildElementCreator from '@/elementCreator'
 | 
			
		||||
import NbRenderer, { NbRendererOpts } from '@/renderer'
 | 
			
		||||
import buildRenderer, { NbRenderer, Options as RendererOpts } from '@/renderer'
 | 
			
		||||
import { DisplayData, MimeBundle, MultilineString, Notebook } from '@/nbformat'
 | 
			
		||||
 | 
			
		||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
			
		||||
import { Anything } from '~/test/support/matchers/toMatchElement'
 | 
			
		||||
import { mockLastResult, mockResults } from '~/test/support/helpers'
 | 
			
		||||
import * as fixtures from './support/fixtures/notebook'
 | 
			
		||||
import * as _fixtures from './support/fixtures/notebook'
 | 
			
		||||
 | 
			
		||||
const document = new Document()
 | 
			
		||||
const fixtures = _fixtures  // workaround to allow indexed access
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
describe('built renderer', () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +27,7 @@ describe('built renderer', () => {
 | 
			
		|||
  const dataRenderers = {
 | 
			
		||||
    'text/custom': rendererMock('DisplayData'),
 | 
			
		||||
  }
 | 
			
		||||
  const rendererOpts: NbRendererOpts<HTMLElement> = {
 | 
			
		||||
  const rendererOpts: RendererOpts<HTMLElement> = {
 | 
			
		||||
    ansiCodesRenderer,
 | 
			
		||||
    codeHighlighter,
 | 
			
		||||
    markdownRenderer,
 | 
			
		||||
| 
						 | 
				
			
			@ -38,46 +37,45 @@ describe('built renderer', () => {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    renderer = new NbRenderer(elementCreator, rendererOpts)
 | 
			
		||||
    renderer = buildRenderer(elementCreator, rendererOpts)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  describe('.render', () => {
 | 
			
		||||
  describe('.Notebook', () => {
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
      renderer.renderCell = rendererMock('Cell')
 | 
			
		||||
      renderer.Cell = rendererMock('Cell')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('returns div.notebook', () => {
 | 
			
		||||
      expect( renderer.render({ ...notebook, cells: [] }) ).toHtmlEqual(
 | 
			
		||||
        <div class="notebook"></div>
 | 
			
		||||
    it('returns div.notebook.worksheet', () => {
 | 
			
		||||
      expect( renderer.Notebook({ ...notebook, cells: [] }) ).toHtmlEqual(
 | 
			
		||||
        <div class="notebook worksheet"></div>
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('returns element with $cells converted using .renderCell() as the children', () => {
 | 
			
		||||
      const result = renderer.render(notebook)
 | 
			
		||||
    it('returns element with $cells converted using .Cell() as the children', () => {
 | 
			
		||||
      const result = renderer.Notebook(notebook)
 | 
			
		||||
 | 
			
		||||
      notebook.cells.forEach((cell, idx) => {
 | 
			
		||||
        expect( renderer.renderCell ).toHaveBeenNthCalledWith(idx + 1, cell, notebook)
 | 
			
		||||
        expect( renderer.Cell ).toHaveBeenNthCalledWith(idx + 1, cell, notebook)
 | 
			
		||||
      })
 | 
			
		||||
      expect( result.children ).toHtmlEqual(mockResults(renderer.renderCell))
 | 
			
		||||
      expect( result.children ).toHtmlEqual(mockResults(renderer.Cell))
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  describe('.renderCell', () => {
 | 
			
		||||
  describe('.Cell', () => {
 | 
			
		||||
 | 
			
		||||
    describe.each([
 | 
			
		||||
      'renderCodeCell', 'renderMarkdownCell', 'renderRawCell',
 | 
			
		||||
    ] as const)('with %s', (funcName) => {
 | 
			
		||||
      const type = funcName.replace('render', '')
 | 
			
		||||
      const cell = (fixtures as any)[type]
 | 
			
		||||
      'CodeCell', 'MarkdownCell', 'RawCell',
 | 
			
		||||
    ] as const)('with %s', (type) => {
 | 
			
		||||
      const cell = fixtures[type]
 | 
			
		||||
 | 
			
		||||
      it(`returns result of calling .${funcName}() with the given cell`, () => {
 | 
			
		||||
      it(`returns result of calling .${type}() with the given cell`, () => {
 | 
			
		||||
        const expected = stubElement(type)
 | 
			
		||||
        const rendererFunc = (renderer as any)[funcName] = jest.fn(() => expected)
 | 
			
		||||
        renderer[type] = jest.fn(() => expected)
 | 
			
		||||
 | 
			
		||||
        expect( renderer.renderCell(cell, notebook) ).toBe(expected)
 | 
			
		||||
        expect( rendererFunc ).toBeCalledWith(cell, notebook)
 | 
			
		||||
        expect( renderer.Cell(cell, notebook) ).toBe(expected)
 | 
			
		||||
        expect( renderer[type] ).toBeCalledWith(cell, notebook)
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +86,7 @@ describe('built renderer', () => {
 | 
			
		|||
      } as any
 | 
			
		||||
 | 
			
		||||
      it('returns div with comment "Unsupported cell type"', () => {
 | 
			
		||||
        expect( renderer.renderCell(cell, notebook) ).toHtmlEqual(
 | 
			
		||||
        expect( renderer.Cell(cell, notebook) ).toHtmlEqual(
 | 
			
		||||
          <div>
 | 
			
		||||
            {{__html: '<!-- Unsupported cell type -->' }}
 | 
			
		||||
          </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -98,15 +96,15 @@ describe('built renderer', () => {
 | 
			
		|||
  })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  describe('.renderMarkdownCell', () => {
 | 
			
		||||
  describe('.MarkdownCell', () => {
 | 
			
		||||
    eachMultilineVariant(fixtures.MarkdownCell, 'source', (cell) => {
 | 
			
		||||
      const source = join(cell.source)
 | 
			
		||||
 | 
			
		||||
      it('returns section.cell.markdown-cell with the $source converted using markdownRenderer() as content', () => {
 | 
			
		||||
        expect( renderer.renderMarkdownCell(cell, notebook) ).toHtmlEqual(
 | 
			
		||||
          <section class="cell markdown-cell">
 | 
			
		||||
      it('returns div.cell.markdown-cell with the $source converted using markdownRenderer() as content', () => {
 | 
			
		||||
        expect( renderer.MarkdownCell(cell, notebook) ).toHtmlEqual(
 | 
			
		||||
          <div class="cell markdown-cell">
 | 
			
		||||
            {{__html: mockLastResult(markdownRenderer) }}
 | 
			
		||||
          </section>
 | 
			
		||||
          </div>
 | 
			
		||||
        )
 | 
			
		||||
        expect( markdownRenderer ).toBeCalledWith(source)
 | 
			
		||||
      })
 | 
			
		||||
| 
						 | 
				
			
			@ -114,48 +112,48 @@ describe('built renderer', () => {
 | 
			
		|||
  })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  describe('.renderRawCell', () => {
 | 
			
		||||
  describe('.RawCell', () => {
 | 
			
		||||
    eachMultilineVariant(fixtures.RawCell, 'source', (cell) => {
 | 
			
		||||
 | 
			
		||||
      it('returns section.cell.raw-cell with the $source as content', () => {
 | 
			
		||||
        expect( renderer.renderRawCell(cell, notebook) ).toHtmlEqual(
 | 
			
		||||
          <section class="cell raw-cell">
 | 
			
		||||
      it('returns div.cell.raw-cell with the $source as content', () => {
 | 
			
		||||
        expect( renderer.RawCell(cell, notebook) ).toHtmlEqual(
 | 
			
		||||
          <div class="cell raw-cell">
 | 
			
		||||
            {{__html: join(cell.source) }}
 | 
			
		||||
          </section>
 | 
			
		||||
          </div>
 | 
			
		||||
        )
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  describe('.renderCodeCell', () => {
 | 
			
		||||
  describe('.CodeCell', () => {
 | 
			
		||||
    const cell = fixtures.CodeCell
 | 
			
		||||
    let result: HTMLElement
 | 
			
		||||
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
      renderer.renderSource = rendererMock('Source')
 | 
			
		||||
      renderer.renderOutput = rendererMock('Output')
 | 
			
		||||
      renderer.Source = rendererMock('Source')
 | 
			
		||||
      renderer.Output = rendererMock('Output')
 | 
			
		||||
 | 
			
		||||
      result = renderer.renderCodeCell(cell, notebook)
 | 
			
		||||
      result = renderer.CodeCell(cell, notebook)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('returns section.cell.code-cell', () => {
 | 
			
		||||
    it('returns div.cell.code-cell', () => {
 | 
			
		||||
      expect( result ).toMatchElement(
 | 
			
		||||
        <section class="cell code-cell"><Anything /></section>
 | 
			
		||||
        <div class="cell code-cell"><Anything /></div>
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    describe('with non-empty $source', () => {
 | 
			
		||||
 | 
			
		||||
      it('returns element with $source rendered using .renderSource() as children[0]', () => {
 | 
			
		||||
        expect( renderer.renderSource ).toBeCalledWith(cell, notebook)
 | 
			
		||||
        expect( result.children[0] ).toHtmlEqual(mockLastResult(renderer.renderSource)!)
 | 
			
		||||
      it('returns element with $source rendered using .Source() as children[0]', () => {
 | 
			
		||||
        expect( renderer.Source ).toBeCalledWith(cell, notebook)
 | 
			
		||||
        expect( result.children[0] ).toHtmlEqual(mockLastResult(renderer.Source))
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    describe('with empty $source', () => {
 | 
			
		||||
      beforeEach(() => {
 | 
			
		||||
        result = renderer.renderCodeCell({ ...cell, source: [] }, notebook)
 | 
			
		||||
        result = renderer.CodeCell({ ...cell, source: [] }, notebook)
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      it('returns element with empty div as children[0]', () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -165,22 +163,22 @@ describe('built renderer', () => {
 | 
			
		|||
      })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('returns element with $outputs rendered using .renderOutput() as children[1+]', () => {
 | 
			
		||||
    it('returns element with $outputs rendered using .Output() as children[1+]', () => {
 | 
			
		||||
      cell.outputs.forEach((output, idx) => {
 | 
			
		||||
        expect( renderer.renderOutput ).toHaveBeenNthCalledWith(idx + 1, output, cell)
 | 
			
		||||
        expect( renderer.Output ).toHaveBeenNthCalledWith(idx + 1, output, cell)
 | 
			
		||||
      })
 | 
			
		||||
      expect( result.children.slice(1) ).toHtmlEqual(mockResults(renderer.renderOutput))
 | 
			
		||||
      expect( result.children.slice(1) ).toHtmlEqual(mockResults(renderer.Output))
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  describe('.renderSource', () => {
 | 
			
		||||
  describe('.Source', () => {
 | 
			
		||||
    const cell = fixtures.CodeCell
 | 
			
		||||
    const notebookLang = notebook.metadata.language_info!.name
 | 
			
		||||
    let result: HTMLElement
 | 
			
		||||
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
      result = renderer.renderSource(cell, notebook)
 | 
			
		||||
      result = renderer.Source(cell, notebook)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('returns div > pre > code', () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -208,7 +206,7 @@ describe('built renderer', () => {
 | 
			
		|||
        const myCell = { ...cell, execution_count: 2 }
 | 
			
		||||
 | 
			
		||||
        it('has data-execution-count and data-prompt-number attributes', () => {
 | 
			
		||||
          const result = renderer.renderSource(myCell, notebook)
 | 
			
		||||
          const result = renderer.Source(myCell, notebook)
 | 
			
		||||
 | 
			
		||||
          expect( result.attributes ).toMatchObject({
 | 
			
		||||
            'data-execution-count': String(myCell.execution_count),
 | 
			
		||||
| 
						 | 
				
			
			@ -221,7 +219,7 @@ describe('built renderer', () => {
 | 
			
		|||
        const myCell = { ...cell, execution_count: null }
 | 
			
		||||
 | 
			
		||||
        it('has data-execution-count and data-prompt-number attributes', () => {
 | 
			
		||||
          const result = renderer.renderSource(myCell, notebook)
 | 
			
		||||
          const result = renderer.Source(myCell, notebook)
 | 
			
		||||
 | 
			
		||||
          expect( result.attributes )
 | 
			
		||||
            .not.toHaveProperty('data-execution-count')
 | 
			
		||||
| 
						 | 
				
			
			@ -234,7 +232,7 @@ describe('built renderer', () => {
 | 
			
		|||
      let codeEl: HTMLElement
 | 
			
		||||
 | 
			
		||||
      beforeEach(() => {
 | 
			
		||||
        codeEl = renderer.renderSource(cell, notebook).firstChild!.firstChild as HTMLElement
 | 
			
		||||
        codeEl = renderer.Source(cell, notebook).firstChild!.firstChild as HTMLElement
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      it("has class lang-<lang> where lang is the notebook's language", () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -256,7 +254,7 @@ describe('built renderer', () => {
 | 
			
		|||
      const notebookLang = 'python'
 | 
			
		||||
 | 
			
		||||
      it('uses the default language: python', () => {
 | 
			
		||||
        const result = renderer.renderSource(cell, myNotebook)
 | 
			
		||||
        const result = renderer.Source(cell, myNotebook)
 | 
			
		||||
        const codeEl = result.firstChild!.firstChild as HTMLElement
 | 
			
		||||
 | 
			
		||||
        expect( codeEl.getAttribute('data-language') ).toBe(notebookLang)
 | 
			
		||||
| 
						 | 
				
			
			@ -267,20 +265,19 @@ describe('built renderer', () => {
 | 
			
		|||
  })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  describe('.renderOutput', () => {
 | 
			
		||||
  describe('.Output', () => {
 | 
			
		||||
    const cell = { ...fixtures.CodeCell, execution_count: null }
 | 
			
		||||
 | 
			
		||||
    describe.each([
 | 
			
		||||
      'renderDisplayData', 'renderExecuteResult', 'renderStream', 'renderError',
 | 
			
		||||
    ] as const)('with %s output', (funcName) => {
 | 
			
		||||
      'DisplayData', 'ExecuteResult', 'Stream', 'Error',
 | 
			
		||||
    ] as const)('with %s output', (type) => {
 | 
			
		||||
 | 
			
		||||
      const type = funcName.replace('render', '')
 | 
			
		||||
      const output = (fixtures as any)[type]
 | 
			
		||||
      const output = fixtures[type]
 | 
			
		||||
      let result: HTMLElement
 | 
			
		||||
 | 
			
		||||
      beforeEach(() => {
 | 
			
		||||
        renderer[funcName] = rendererMock(type)
 | 
			
		||||
        result = renderer.renderOutput(output, cell)
 | 
			
		||||
        renderer[type] = rendererMock(type)
 | 
			
		||||
        result = renderer.Output(output, cell)
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      it('returns div.output', () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -289,16 +286,16 @@ describe('built renderer', () => {
 | 
			
		|||
        )
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      it(`returns element with the output rendered using .${funcName}() as the only child`, () => {
 | 
			
		||||
        expect( renderer[funcName] ).toBeCalledWith(output)
 | 
			
		||||
        expect( result.children ).toHtmlEqual([mockLastResult(renderer[funcName])!])
 | 
			
		||||
      it(`returns element with the output rendered using .${type}() as the only child`, () => {
 | 
			
		||||
        expect( renderer[type] ).toBeCalledWith(output)
 | 
			
		||||
        expect( result.children ).toHtmlEqual([mockLastResult(renderer[type])])
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      describe('when the cell has non-null execution_count', () => {
 | 
			
		||||
        const cell = { ...fixtures.CodeCell, execution_count: 2 }
 | 
			
		||||
 | 
			
		||||
        it('returns element with attributes data-execution-count and data-prompt-number', () => {
 | 
			
		||||
          const result = renderer.renderOutput(output, cell)
 | 
			
		||||
          const result = renderer.Output(output, cell)
 | 
			
		||||
 | 
			
		||||
          expect( result.attributes ).toMatchObject({
 | 
			
		||||
            'data-execution-count': String(cell.execution_count),
 | 
			
		||||
| 
						 | 
				
			
			@ -320,7 +317,7 @@ describe('built renderer', () => {
 | 
			
		|||
      }
 | 
			
		||||
 | 
			
		||||
      it('returns div with comment "Unsupported output type"', () => {
 | 
			
		||||
        expect( renderer.renderOutput(output, cell) ).toHtmlEqual(
 | 
			
		||||
        expect( renderer.Output(output, cell) ).toHtmlEqual(
 | 
			
		||||
          <div class="output">
 | 
			
		||||
            <div>
 | 
			
		||||
              {{__html: '<!-- Unsupported output type -->' }}
 | 
			
		||||
| 
						 | 
				
			
			@ -332,7 +329,7 @@ describe('built renderer', () => {
 | 
			
		|||
  })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  describe('.renderDisplayData', () => {
 | 
			
		||||
  describe('.DisplayData', () => {
 | 
			
		||||
 | 
			
		||||
    function displayDataWith (data: MimeBundle): DisplayData {
 | 
			
		||||
      return { ...fixtures.DisplayData, data }
 | 
			
		||||
| 
						 | 
				
			
			@ -361,7 +358,7 @@ describe('built renderer', () => {
 | 
			
		|||
      const displayData = displayDataWith({ 'text/non-sense': 'whaat' })
 | 
			
		||||
 | 
			
		||||
      it('returns div.empty-output', () => {
 | 
			
		||||
        expect( renderer.renderDisplayData(displayData) ).toHtmlEqual(
 | 
			
		||||
        expect( renderer.DisplayData(displayData) ).toHtmlEqual(
 | 
			
		||||
          <div class="empty-output"></div>
 | 
			
		||||
        )
 | 
			
		||||
      })
 | 
			
		||||
| 
						 | 
				
			
			@ -373,7 +370,7 @@ describe('built renderer', () => {
 | 
			
		|||
        withMimeData(mimeType, ['aW1hZ2Ug\n', 'ZGF0YQ=='], (output) => {
 | 
			
		||||
 | 
			
		||||
          it('returns img.image-output with the data in the src attribute', () => {
 | 
			
		||||
            expect( renderer.renderDisplayData(output) ).toHtmlEqual(
 | 
			
		||||
            expect( renderer.DisplayData(output) ).toHtmlEqual(
 | 
			
		||||
              <img class="image-output" src={`data:${mimeType};base64,aW1hZ2UgZGF0YQ==`}></img>
 | 
			
		||||
            )
 | 
			
		||||
          })
 | 
			
		||||
| 
						 | 
				
			
			@ -391,7 +388,7 @@ describe('built renderer', () => {
 | 
			
		|||
        withMimeData(mimeType, '<stub>data</stub>', (output, data) => {
 | 
			
		||||
 | 
			
		||||
          it(`returns div${classes.map(x => `.${x}`)} with the data as content`, () => {
 | 
			
		||||
            expect( renderer.renderDisplayData(output) ).toHtmlEqual(
 | 
			
		||||
            expect( renderer.DisplayData(output) ).toHtmlEqual(
 | 
			
		||||
              <div class={ classes.join(' ') }>
 | 
			
		||||
                {{__html: join(data) }}
 | 
			
		||||
              </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -403,7 +400,7 @@ describe('built renderer', () => {
 | 
			
		|||
      withMimeData('text/markdown', ['Lorem\n', 'ipsum'], (output, data) => {
 | 
			
		||||
 | 
			
		||||
        it('returns div.html-output with the data converted using markdownRenderer() as content', () => {
 | 
			
		||||
          expect( renderer.renderDisplayData(output) ).toHtmlEqual(
 | 
			
		||||
          expect( renderer.DisplayData(output) ).toHtmlEqual(
 | 
			
		||||
            <div class="html-output">
 | 
			
		||||
              {{__html: mockLastResult(markdownRenderer) }}
 | 
			
		||||
            </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -415,7 +412,7 @@ describe('built renderer', () => {
 | 
			
		|||
      withMimeData('text/plain', '>_<', (output) => {
 | 
			
		||||
 | 
			
		||||
        it('returns pre.text-output with html-escaped data', () => {
 | 
			
		||||
          expect( renderer.renderDisplayData(output) ).toHtmlEqual(
 | 
			
		||||
          expect( renderer.DisplayData(output) ).toHtmlEqual(
 | 
			
		||||
            <pre class="text-output">{ '>_<' }</pre>
 | 
			
		||||
          )
 | 
			
		||||
        })
 | 
			
		||||
| 
						 | 
				
			
			@ -424,7 +421,7 @@ describe('built renderer', () => {
 | 
			
		|||
      withMimeData('application/javascript', 'alert("Hello &!")', (output, data) => {
 | 
			
		||||
 | 
			
		||||
        it('returns script with the data', () => {
 | 
			
		||||
          expect( renderer.renderDisplayData(output) ).toHtmlEqual(
 | 
			
		||||
          expect( renderer.DisplayData(output) ).toHtmlEqual(
 | 
			
		||||
            <script>{{__html: join(data) }}</script>
 | 
			
		||||
          )
 | 
			
		||||
        })
 | 
			
		||||
| 
						 | 
				
			
			@ -436,8 +433,8 @@ describe('built renderer', () => {
 | 
			
		|||
      withMimeData('text/custom', 'Lorem ipsum', (output, data) => {
 | 
			
		||||
 | 
			
		||||
        it('renders the data using the associated external renderer', () => {
 | 
			
		||||
          expect( renderer.renderDisplayData(output) ).toHtmlEqual(
 | 
			
		||||
            mockLastResult(dataRenderers['text/custom'])!
 | 
			
		||||
          expect( renderer.DisplayData(output) ).toHtmlEqual(
 | 
			
		||||
            mockLastResult(dataRenderers['text/custom'])
 | 
			
		||||
          )
 | 
			
		||||
          expect( dataRenderers['text/custom'] ).toBeCalledWith(join(data))
 | 
			
		||||
        })
 | 
			
		||||
| 
						 | 
				
			
			@ -453,7 +450,7 @@ describe('built renderer', () => {
 | 
			
		|||
      const output = displayDataWith(mimeBundle)
 | 
			
		||||
 | 
			
		||||
      it('renders the data of the MIME type with a higher priority', () => {
 | 
			
		||||
        expect( renderer.renderDisplayData(output) ).toHtmlEqual(
 | 
			
		||||
        expect( renderer.DisplayData(output) ).toHtmlEqual(
 | 
			
		||||
          <div class="html-output">
 | 
			
		||||
            {{__html: mimeBundle['text/html'] }}
 | 
			
		||||
          </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -467,8 +464,8 @@ describe('built renderer', () => {
 | 
			
		|||
        }
 | 
			
		||||
        const output = displayDataWith(mimeBundle)
 | 
			
		||||
 | 
			
		||||
        expect( renderer.renderDisplayData(output) ).toHtmlEqual(
 | 
			
		||||
          mockLastResult(dataRenderers['text/custom'])!
 | 
			
		||||
        expect( renderer.DisplayData(output) ).toHtmlEqual(
 | 
			
		||||
          mockLastResult(dataRenderers['text/custom'])
 | 
			
		||||
        )
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
| 
						 | 
				
			
			@ -477,7 +474,7 @@ describe('built renderer', () => {
 | 
			
		|||
      const dataRenderer = rendererMock('DisplayData')
 | 
			
		||||
 | 
			
		||||
      beforeEach(() => {
 | 
			
		||||
        renderer = new NbRenderer(elementCreator, {
 | 
			
		||||
        renderer = buildRenderer(elementCreator, {
 | 
			
		||||
          ...rendererOpts,
 | 
			
		||||
          dataRenderers: { 'text/plain': dataRenderer },
 | 
			
		||||
        })
 | 
			
		||||
| 
						 | 
				
			
			@ -487,19 +484,19 @@ describe('built renderer', () => {
 | 
			
		|||
        const data = 'allons-y!'
 | 
			
		||||
        const output = displayDataWith({ 'text/plain': [data] })
 | 
			
		||||
 | 
			
		||||
        expect( renderer.renderDisplayData(output) ).toBe(mockLastResult(dataRenderer))
 | 
			
		||||
        expect( renderer.DisplayData(output) ).toBe(mockLastResult(dataRenderer))
 | 
			
		||||
        expect( dataRenderer ).toBeCalledWith(data)
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  describe('.renderError', () => {
 | 
			
		||||
  describe('.Error', () => {
 | 
			
		||||
    const error = fixtures.Error
 | 
			
		||||
    const traceback = error.traceback.join('\n')
 | 
			
		||||
 | 
			
		||||
    it('returns pre.error.pyerr with inner $traceback converted using ansiCodesRenderer', () => {
 | 
			
		||||
      expect( renderer.renderError(error) ).toHtmlEqual(
 | 
			
		||||
      expect( renderer.Error(error) ).toHtmlEqual(
 | 
			
		||||
        <pre class="error pyerr">
 | 
			
		||||
          {{__html: mockLastResult(ansiCodesRenderer) }}
 | 
			
		||||
        </pre>
 | 
			
		||||
| 
						 | 
				
			
			@ -509,12 +506,12 @@ describe('built renderer', () => {
 | 
			
		|||
  })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  describe('.renderStream', () => {
 | 
			
		||||
  describe('.Stream', () => {
 | 
			
		||||
    eachMultilineVariant(fixtures.Stream, 'text', (stream) => {
 | 
			
		||||
      const text = join(stream.text)
 | 
			
		||||
 | 
			
		||||
      it('returns pre.$name with inner $text converted using ansiCodesRenderer', () => {
 | 
			
		||||
        expect( renderer.renderStream(stream) ).toHtmlEqual(
 | 
			
		||||
        expect( renderer.Stream(stream) ).toHtmlEqual(
 | 
			
		||||
          <pre class={ stream.name }>
 | 
			
		||||
            {{__html: mockLastResult(ansiCodesRenderer) }}
 | 
			
		||||
          </pre>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,5 @@
 | 
			
		|||
// This file is needed only for VSCode, see https://github.com/palmerhq/tsdx/issues/84.
 | 
			
		||||
{
 | 
			
		||||
  "extends": "../../../tsconfig.test.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "baseUrl": ".",
 | 
			
		||||
  },
 | 
			
		||||
  "references": [
 | 
			
		||||
    { "path": "../" },
 | 
			
		||||
  ],
 | 
			
		||||
  "extends": "../tsconfig.json",
 | 
			
		||||
  "include": ["."],
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,11 @@
 | 
			
		|||
    "outDir": "./lib",
 | 
			
		||||
    "tsBuildInfoFile": "./.tsbuildinfo",
 | 
			
		||||
    "baseUrl": ".",
 | 
			
		||||
    "paths": {
 | 
			
		||||
      "*": ["../../types/*"],
 | 
			
		||||
      "@/*": ["./src/*"],
 | 
			
		||||
      "~/*": ["../../*"],
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  "include": [
 | 
			
		||||
    "./src",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "ipynb2html",
 | 
			
		||||
  "version": "0.3.0",
 | 
			
		||||
  "version": "0.1.0-beta.7",
 | 
			
		||||
  "description": "Convert Jupyter Notebook to static HTML",
 | 
			
		||||
  "author": "Jakub Jirutka <jakub@jirutka.cz>",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
| 
						 | 
				
			
			@ -23,18 +23,15 @@
 | 
			
		|||
  "files": [
 | 
			
		||||
    "dist/ipynb2html.min.js*",
 | 
			
		||||
    "dist/ipynb2html-full.min.js*",
 | 
			
		||||
    "dist/notebook.min.css*",
 | 
			
		||||
    "lib",
 | 
			
		||||
    "src",
 | 
			
		||||
    "styles"
 | 
			
		||||
    "src"
 | 
			
		||||
  ],
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build": "ttsc --build",
 | 
			
		||||
    "bundle": "rollup -c",
 | 
			
		||||
    "clean": "rimraf coverage/ dist/ lib/ .eslintcache .tsbuildinfo",
 | 
			
		||||
    "lint": "PKGDIR=$PWD; cd ../../ && eslint --cache --ext .ts,.tsx,.js $PKGDIR",
 | 
			
		||||
    "minify-css": "csso styles/notebook.css -o dist/notebook.min.css -s dist/notebook.min.css.map",
 | 
			
		||||
    "prepublishOnly": "run-p bundle minify-css readme2md",
 | 
			
		||||
    "clean": "rimraf coverage/ dist/ lib/ .tsbuildinfo",
 | 
			
		||||
    "lint": "eslint --ext .ts,.tsx,.js .",
 | 
			
		||||
    "prepublishOnly": "run-p bundle readme2md",
 | 
			
		||||
    "test": "jest --detectOpenHandles --coverage --verbose",
 | 
			
		||||
    "readme2md": "../../scripts/adoc2md -a npm-readme ../../README.adoc > README.md",
 | 
			
		||||
    "watch-ts": "ttsc --build --watch"
 | 
			
		||||
| 
						 | 
				
			
			@ -44,15 +41,10 @@
 | 
			
		|||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "anser": "^1.4.9",
 | 
			
		||||
    "highlight.js": "^10.7.3",
 | 
			
		||||
    "ipynb2html-core": "0.3.0",
 | 
			
		||||
    "katex": "^0.13.11",
 | 
			
		||||
    "marked": "^2.0.7"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/katex": "^0.11.0",
 | 
			
		||||
    "@types/marked": "^2.0.3",
 | 
			
		||||
    "ansi_up": "^5.0.1"
 | 
			
		||||
    "highlightjs": "^9.12.0",
 | 
			
		||||
    "ipynb2html-core": "0.1.0-beta.7",
 | 
			
		||||
    "katex": "^0.11.0",
 | 
			
		||||
    "marked": "^0.7.0"
 | 
			
		||||
  },
 | 
			
		||||
  "peerDependencies": {
 | 
			
		||||
    "nodom": "^2.3.0"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,7 @@
 | 
			
		|||
import addGitMsg from 'rollup-plugin-add-git-msg'
 | 
			
		||||
import babel from '@rollup/plugin-babel'
 | 
			
		||||
import commonjs from '@rollup/plugin-commonjs'
 | 
			
		||||
import license from 'rollup-plugin-node-license'
 | 
			
		||||
import resolve from '@rollup/plugin-node-resolve'
 | 
			
		||||
import babel from 'rollup-plugin-babel'
 | 
			
		||||
import commonjs from 'rollup-plugin-commonjs'
 | 
			
		||||
import resolve from 'rollup-plugin-node-resolve'
 | 
			
		||||
import { terser } from 'rollup-plugin-terser'
 | 
			
		||||
import ttypescript from 'ttypescript'
 | 
			
		||||
import typescript from 'rollup-plugin-typescript2'
 | 
			
		||||
| 
						 | 
				
			
			@ -13,10 +12,10 @@ import pkg from './package.json'
 | 
			
		|||
const extensions = ['.mjs', '.js', '.ts']
 | 
			
		||||
 | 
			
		||||
const globals = {
 | 
			
		||||
  'anser': 'anser',
 | 
			
		||||
  'highlight.js': 'hljs',
 | 
			
		||||
  'katex': 'katex',
 | 
			
		||||
  'marked': 'marked',
 | 
			
		||||
  anser: 'anser',
 | 
			
		||||
  highlightjs: 'hljs',
 | 
			
		||||
  katex: 'katex',
 | 
			
		||||
  marked: 'marked',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const plugins = [
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +32,6 @@ const plugins = [
 | 
			
		|||
        incremental: true,
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    clean: true,
 | 
			
		||||
  }),
 | 
			
		||||
  // Resolve node modules.
 | 
			
		||||
  resolve({
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +43,6 @@ const plugins = [
 | 
			
		|||
  // Transpile all sources for older browsers and inject needed polyfills.
 | 
			
		||||
  babel({
 | 
			
		||||
    babelrc: false,
 | 
			
		||||
    babelHelpers: 'bundled',
 | 
			
		||||
    // To avoid Babel injecting core-js polyfills into core-js.
 | 
			
		||||
    exclude: [/node_modules\/core-js\//],
 | 
			
		||||
    extensions,
 | 
			
		||||
| 
						 | 
				
			
			@ -68,25 +65,22 @@ const plugins = [
 | 
			
		|||
      '* This project is licensed under the terms of the MIT license.'
 | 
			
		||||
    ].join('\n'),
 | 
			
		||||
  }),
 | 
			
		||||
  // Generate table of the bundled packages at top of the file.
 | 
			
		||||
  license({ format: 'table' }),
 | 
			
		||||
  // Minify JS.
 | 
			
		||||
  terser({
 | 
			
		||||
    ecma: 5,
 | 
			
		||||
    include: [/^.+\.min\.js$/],
 | 
			
		||||
    output: {
 | 
			
		||||
      // Preserve comment injected by addGitMsg.
 | 
			
		||||
      comments: RegExp(`\\$\\{${pkg.name}\\}`),
 | 
			
		||||
    },
 | 
			
		||||
  }),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
const output = (filename, extra = {}) => [false, true].map(minify => ({
 | 
			
		||||
const output = (filename, extra = {}) => ['.js', '.min.js'].map(ext => ({
 | 
			
		||||
  name: pkg.name,
 | 
			
		||||
  file: `${filename}${minify ? '.min.js' : '.js'}`,
 | 
			
		||||
  file: `${filename}${ext}`,
 | 
			
		||||
  format: 'umd',
 | 
			
		||||
  sourcemap: true,
 | 
			
		||||
  plugins: [
 | 
			
		||||
    // Minify JS when building .min.js file.
 | 
			
		||||
    minify && terser({
 | 
			
		||||
      ecma: 5,
 | 
			
		||||
      output: {
 | 
			
		||||
        // Preserve comment injected by addGitMsg and license.
 | 
			
		||||
        comments: RegExp(`(?:\\$\\{${pkg.name}\\}|Bundled npm packages)`),
 | 
			
		||||
      },
 | 
			
		||||
    }),
 | 
			
		||||
  ].filter(Boolean),
 | 
			
		||||
  ...extra,
 | 
			
		||||
}))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ function unescapeHTML (input: string): string {
 | 
			
		|||
  return new DOMParser()
 | 
			
		||||
    .parseFromString(input, 'text/html')
 | 
			
		||||
    .documentElement
 | 
			
		||||
    .textContent ?? ''
 | 
			
		||||
    .textContent || ''
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,6 @@ export function autoRender (opts: NbRendererOpts = {}): void {
 | 
			
		|||
 | 
			
		||||
  document.querySelectorAll(selector).forEach(script => {
 | 
			
		||||
    if (script.textContent && script.parentElement) {
 | 
			
		||||
      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
 | 
			
		||||
      const notebook = JSON.parse(unescapeHTML(script.textContent))
 | 
			
		||||
      const nbElement = render(notebook)
 | 
			
		||||
      script.parentElement.replaceChild(nbElement, script)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								packages/ipynb2html/src/global.d.ts
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								packages/ipynb2html/src/global.d.ts
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -2,5 +2,6 @@
 | 
			
		|||
// via global variable. It's an alternative to Anser that doesn't provide
 | 
			
		||||
// bundle for browsers.
 | 
			
		||||
declare class AnsiUp {
 | 
			
		||||
  // eslint-disable-next-line @typescript-eslint/camelcase
 | 
			
		||||
  ansi_to_html (input: string): string
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,18 +1,19 @@
 | 
			
		|||
import anser from 'anser'
 | 
			
		||||
import hljs from 'highlight.js'
 | 
			
		||||
import hljs from 'highlightjs'
 | 
			
		||||
import katex, { KatexOptions } from 'katex'
 | 
			
		||||
import marked from 'marked'
 | 
			
		||||
import marked, { MarkedOptions } from 'marked'
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  createElementCreator,
 | 
			
		||||
  createHtmlRenderer,
 | 
			
		||||
  createNbRenderer,
 | 
			
		||||
  MinimalElement,
 | 
			
		||||
  NbRenderer,
 | 
			
		||||
  NbRendererOpts as BaseOptions,
 | 
			
		||||
  Notebook,
 | 
			
		||||
} from 'ipynb2html-core'
 | 
			
		||||
 | 
			
		||||
import buildMarkdownRenderer, { MarkedOptions } from './markdownRenderer'
 | 
			
		||||
import buildMarkdownRenderer from './markdownRenderer'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export { default as version } from './version'
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +43,7 @@ export type NbRendererOpts<TElement = HTMLElement> = BaseOptions<TElement> & {
 | 
			
		|||
 * for this module's function.
 | 
			
		||||
 */
 | 
			
		||||
type MinimalDocument<TElement extends MinimalElement> = {
 | 
			
		||||
  createElement: (tag: string) => TElement,
 | 
			
		||||
  createElement (tag: string): TElement,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const defaultKatexOpts: KatexOptions = {
 | 
			
		||||
| 
						 | 
				
			
			@ -50,14 +51,9 @@ const defaultKatexOpts: KatexOptions = {
 | 
			
		|||
  throwOnError: false,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const defaultMarkedOpts: MarkedOptions = {
 | 
			
		||||
  headerAnchors: true,
 | 
			
		||||
  headerIdsStripAccents: true,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function hljsCodeHighlighter (code: string, lang: string): string {
 | 
			
		||||
  return hljs.getLanguage(lang)
 | 
			
		||||
    ? hljs.highlight(code, { language: lang }).value
 | 
			
		||||
    ? hljs.highlight(lang, code).value
 | 
			
		||||
    : code
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -120,15 +116,18 @@ export function createRenderer <TElement extends MinimalElement> (
 | 
			
		|||
    codeHighlighter = hljsCodeHighlighter
 | 
			
		||||
  }
 | 
			
		||||
  if (!markdownRenderer && marked) {
 | 
			
		||||
    const markedOpts = { ...defaultMarkedOpts, ...opts.markedOpts }
 | 
			
		||||
    markdownRenderer = buildMarkdownRenderer(markedOpts, katexOpts)
 | 
			
		||||
    if (katex) {
 | 
			
		||||
      markdownRenderer = buildMarkdownRenderer(opts.markedOpts, katexOpts)
 | 
			
		||||
    } else {
 | 
			
		||||
      markdownRenderer = (text) => marked.parse(text, opts.markedOpts)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (!dataRenderers['text/html'] && katex) {
 | 
			
		||||
    const mathRenderer = (tex: string) => katex.renderToString(tex, katexOpts)
 | 
			
		||||
    dataRenderers['text/html'] = createHtmlRenderer({ elementCreator, mathRenderer })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return new NbRenderer(elementCreator, {
 | 
			
		||||
  return createNbRenderer(elementCreator, {
 | 
			
		||||
    ansiCodesRenderer,
 | 
			
		||||
    codeHighlighter,
 | 
			
		||||
    dataRenderers,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,86 +1,38 @@
 | 
			
		|||
import hljs from 'highlight.js'
 | 
			
		||||
import hljs from 'highlightjs'
 | 
			
		||||
import katex, { KatexOptions } from 'katex'
 | 
			
		||||
import marked, { Slugger } from 'marked'
 | 
			
		||||
import marked, { MarkedOptions } from 'marked'
 | 
			
		||||
 | 
			
		||||
import { mathExtractor } from 'ipynb2html-core'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export type MarkdownRenderer = (markdown: string) => string
 | 
			
		||||
 | 
			
		||||
export interface MarkedOptions extends marked.MarkedOptions {
 | 
			
		||||
  /** Generate heading anchors (this implies headingIds). */
 | 
			
		||||
  headerAnchors?: boolean
 | 
			
		||||
  headerIdsStripAccents?: boolean
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Removes accents from the given string.
 | 
			
		||||
const stripAccents = (text: string) => text.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
 | 
			
		||||
 | 
			
		||||
// Removes math markers from the given string.
 | 
			
		||||
const stripMath = (text: string) => mathExtractor.restoreMath(text, []).trim()
 | 
			
		||||
 | 
			
		||||
class Renderer extends marked.Renderer {
 | 
			
		||||
 | 
			
		||||
  heading (text: string, level: 1 | 2 | 3 | 4 | 5 | 6, raw: string, slugger: Slugger): string {
 | 
			
		||||
    const opts = this.options as MarkedOptions
 | 
			
		||||
 | 
			
		||||
    if (!opts.headerIds && !opts.headerAnchors) {
 | 
			
		||||
      return super.heading(text, level, raw, slugger)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let id = (opts.headerPrefix ?? '') + slugger.slug(stripMath(raw))
 | 
			
		||||
    if (opts.headerIdsStripAccents) {
 | 
			
		||||
      id = stripAccents(id)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (opts.headerAnchors) {
 | 
			
		||||
      text = `<a class="anchor" href="#${id}" aria-hidden="true"></a>${text}`
 | 
			
		||||
    }
 | 
			
		||||
    return `<h${level} id="${id}">${text}</h${level}>`
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  link (href: string | null, title: string | null, text: string): string {
 | 
			
		||||
    return super.link(href && stripMath(href), title && stripMath(title), text)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  image (href: string | null, title: string | null, text: string): string {
 | 
			
		||||
    return super.image(href && stripMath(href), title && stripMath(title), stripMath(text))
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function highlight (code: string, lang: string): string {
 | 
			
		||||
  return hljs.getLanguage(lang)
 | 
			
		||||
    ? hljs.highlight(code, { language: lang, ignoreIllegals: true }).value
 | 
			
		||||
    ? hljs.highlight(lang, code, true).value
 | 
			
		||||
    : code
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const renderer = (markedOpts: MarkedOptions) => (markdown: string) => marked.parse(markdown, markedOpts)
 | 
			
		||||
 | 
			
		||||
const rendererWithMath = (markedOpts: MarkedOptions, katexOpts: KatexOptions) => (markdown: string) => {
 | 
			
		||||
  const [text, math] = mathExtractor.extractMath(markdown)
 | 
			
		||||
  const html = marked.parse(text, markedOpts)
 | 
			
		||||
 | 
			
		||||
  const mathHtml = math.map(({ value, displayMode }) => {
 | 
			
		||||
    return katex.renderToString(value, { ...katexOpts, displayMode })
 | 
			
		||||
  })
 | 
			
		||||
  return mathExtractor.restoreMath(html, mathHtml)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns a pre-configured marked parser with (optional) math support (using
 | 
			
		||||
 * KaTeX) and code highlighter (highlight.js).
 | 
			
		||||
 * Returns a pre-configured marked parser with math support (using KaTeX)
 | 
			
		||||
 * and code highlighter (highlight.js).
 | 
			
		||||
 *
 | 
			
		||||
 * @param {MarkedOptions} markedOpts Options for the marked Markdown renderer.
 | 
			
		||||
 * @param {KatexOptions} katexOpts Options for the KaTeX math renderer.
 | 
			
		||||
 */
 | 
			
		||||
export default (markedOpts: MarkedOptions = {}, katexOpts: KatexOptions = {}): MarkdownRenderer => {
 | 
			
		||||
 | 
			
		||||
  markedOpts = { renderer: new Renderer(markedOpts), ...markedOpts }
 | 
			
		||||
  if (hljs) {  // highlight.js may be an optional dependency (in browser bundle)
 | 
			
		||||
export default (markedOpts: MarkedOptions = {}, katexOpts: KatexOptions = {}) => {
 | 
			
		||||
  if (hljs) {  // highlightjs may be an optional dependency (in browser bundle)
 | 
			
		||||
    markedOpts = { highlight, ...markedOpts }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return katex  // katex may be an optional dependency (in browser bundle)
 | 
			
		||||
    ? rendererWithMath(markedOpts, katexOpts)
 | 
			
		||||
    : renderer(markedOpts)
 | 
			
		||||
  /**
 | 
			
		||||
   * Converts the given *markdown* into HTML.
 | 
			
		||||
   */
 | 
			
		||||
  return (markdown: string): string => {
 | 
			
		||||
    const [text, math] = mathExtractor.extractMath(markdown)
 | 
			
		||||
    const html = marked.parse(text, markedOpts)
 | 
			
		||||
 | 
			
		||||
    const mathHtml = math.map(({ value, displayMode }) => {
 | 
			
		||||
      return katex.renderToString(value, { ...katexOpts, displayMode })
 | 
			
		||||
    })
 | 
			
		||||
    return mathExtractor.restoreMath(html, mathHtml)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,18 +3,18 @@ import marked from 'marked'
 | 
			
		|||
import { Notebook } from 'ipynb2html-core'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EmptyRenderer extends marked.Renderer {}
 | 
			
		||||
class EmptyRenderer extends marked.Renderer {
 | 
			
		||||
 | 
			
		||||
// Override all the EmptyRenderer's methods inherited from marked.Renderer to
 | 
			
		||||
// always return an empty string.
 | 
			
		||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
 | 
			
		||||
const RendererProto = marked.Renderer.prototype
 | 
			
		||||
for (const prop of Object.getOwnPropertyNames(RendererProto)) {
 | 
			
		||||
  if (prop !== 'constructor' && typeof (RendererProto as any)[prop] === 'function') {
 | 
			
		||||
    (EmptyRenderer.prototype as any)[prop] = () => ''
 | 
			
		||||
  constructor (options?: marked.MarkedOptions) {
 | 
			
		||||
    super(options)
 | 
			
		||||
 | 
			
		||||
    for (const prop in this) {
 | 
			
		||||
      if (this[prop] instanceof Function) {
 | 
			
		||||
        (this as any)[prop] = () => ''
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
 | 
			
		||||
 | 
			
		||||
class MainTitleRenderer extends EmptyRenderer {
 | 
			
		||||
  _titleFound = false
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
import { $INLINE_JSON } from 'ts-transformer-inline-file'
 | 
			
		||||
 | 
			
		||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
 | 
			
		||||
const { version } = $INLINE_JSON('../package.json')
 | 
			
		||||
 | 
			
		||||
export default version as string
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,86 +0,0 @@
 | 
			
		|||
/* Reference styles for ipynb2html */
 | 
			
		||||
 | 
			
		||||
.nb-notebook {
 | 
			
		||||
  line-height: 1.5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-cell + .nb-cell {
 | 
			
		||||
  margin-top: 1.4rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-raw-cell {
 | 
			
		||||
  font-family: monospace;
 | 
			
		||||
  white-space: pre-wrap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-code-cell {
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-source::before,
 | 
			
		||||
.nb-output::before {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  font-family: monospace;
 | 
			
		||||
  color: #999;
 | 
			
		||||
  left: -7.5em;
 | 
			
		||||
  width: 7em;
 | 
			
		||||
  text-align: right;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-source::before {
 | 
			
		||||
  content: "In [" attr(data-execution-count) "]:";
 | 
			
		||||
}
 | 
			
		||||
.nb-output::before {
 | 
			
		||||
  content: "Out[" attr(data-execution-count) "]:";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-source + .nb-output,
 | 
			
		||||
.nb-output + .nb-output {
 | 
			
		||||
  margin-top: 1.4rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-source > pre {
 | 
			
		||||
  background-color: #f7f7f7;
 | 
			
		||||
  border: 1px solid #cfcfcf;
 | 
			
		||||
  border-radius: 2px;
 | 
			
		||||
  padding: 0.5em;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  overflow-x: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-output {
 | 
			
		||||
  min-height: 1em;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-output > pre {
 | 
			
		||||
  padding: 0.5em;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  overflow-x: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-output > img {
 | 
			
		||||
  max-width: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-stdout,
 | 
			
		||||
.nb-stderr {
 | 
			
		||||
  white-space: pre-wrap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nb-error,
 | 
			
		||||
.nb-stderr {
 | 
			
		||||
  background-color: #fdd;
 | 
			
		||||
  border-radius: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (max-width: 768px) {
 | 
			
		||||
  .nb-source::before,
 | 
			
		||||
  .nb-output::before {
 | 
			
		||||
    display: block;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    padding-bottom: 0.5em;
 | 
			
		||||
    text-align: left;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								packages/ipynb2html/test/global.d.ts
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								packages/ipynb2html/test/global.d.ts
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1 +0,0 @@
 | 
			
		|||
../src/global.d.ts
 | 
			
		||||
| 
						 | 
				
			
			@ -1,152 +0,0 @@
 | 
			
		|||
import { KatexOptions } from 'katex'
 | 
			
		||||
import parseHtml from 'node-html-parser'
 | 
			
		||||
 | 
			
		||||
import markdownRenderer, { MarkedOptions } from '@/markdownRenderer'
 | 
			
		||||
 | 
			
		||||
import '~/test/setup'  // setupFilesAfterEnv doesn't work here
 | 
			
		||||
import { Anything } from '~/test/support/matchers/toMatchElement'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
let katexOpts: KatexOptions
 | 
			
		||||
let markedOpts: MarkedOptions
 | 
			
		||||
 | 
			
		||||
beforeEach(() => {
 | 
			
		||||
  katexOpts = {
 | 
			
		||||
    displayMode: true,
 | 
			
		||||
    throwOnError: false,
 | 
			
		||||
  }
 | 
			
		||||
  markedOpts = {}
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
describe('headings', () => {
 | 
			
		||||
 | 
			
		||||
  it('renders h tag without anchor', () => {
 | 
			
		||||
    expect( render('## Some Title') ).toHtmlEqual(
 | 
			
		||||
      <h2 id="some-title">Some Title</h2>
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('renders math in text, but strips it in id', () => {
 | 
			
		||||
    expect( render('## Integers $\\mathbb{Z}$') ).toMatchElement(
 | 
			
		||||
      <h2 id="integers">
 | 
			
		||||
        Integers <span class="katex"><Anything /></span>
 | 
			
		||||
      </h2>
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('when headerAnchors is true', () => {
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
      markedOpts = { headerAnchors: true }
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('renders h tag with anchor', () => {
 | 
			
		||||
      expect( render('## Some Title') ).toHtmlEqual(
 | 
			
		||||
        <h2 id="some-title">
 | 
			
		||||
          <a class="anchor" href="#some-title" aria-hidden="true"></a>Some Title
 | 
			
		||||
        </h2>
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('renders math in text, but strips it in href and id', () => {
 | 
			
		||||
      expect( render('## Integers $\\mathbb{Z}$') ).toMatchElement(
 | 
			
		||||
        <h2 id="integers">
 | 
			
		||||
          <a class="anchor" href="#integers" aria-hidden="true"></a>
 | 
			
		||||
          Integers <span class="katex"><Anything /></span>
 | 
			
		||||
        </h2>
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('when headerIds is false', () => {
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
      markedOpts = { headerIds: false }
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('renders h tag without id and anchor', () => {
 | 
			
		||||
      expect( render('## Some Title') ).toHtmlEqual(
 | 
			
		||||
        <h2>Some Title</h2>
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('when headerIdsStripAccents is true', () => {
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
      markedOpts = { headerIdsStripAccents: true }
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('strips accents in generated id', () => {
 | 
			
		||||
      expect( render('## Příliš žluťoučký kůň') ).toHtmlEqual(
 | 
			
		||||
        <h2 id="prilis-zlutoucky-kun">
 | 
			
		||||
          Příliš žluťoučký kůň
 | 
			
		||||
        </h2>
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
describe('link', () => {
 | 
			
		||||
 | 
			
		||||
  it('strips math in title', () => {
 | 
			
		||||
    expect( render('[link](https://example.org "This is $\\TeX$!")') ).toHtmlEqual(
 | 
			
		||||
      <p><a href="https://example.org" title="This is !">link</a></p>
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('strips math in href', () => {
 | 
			
		||||
    expect( render('[link](https://example.org/$\\TeX$)') ).toHtmlEqual(
 | 
			
		||||
      <p><a href="https://example.org/">link</a></p>
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('renders math in text', () => {
 | 
			
		||||
    expect( render('[This is $\\TeX$!](https://example.org/)') ).toMatchElement(
 | 
			
		||||
      <p><a href="https://example.org/">This is <span class="katex"><Anything /></span>!</a></p>
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
describe('image', () => {
 | 
			
		||||
 | 
			
		||||
  it('strips math in title', () => {
 | 
			
		||||
    expect( render('') ).toHtmlEqual(
 | 
			
		||||
      <p><img src="https://example.org/img.png" alt="x" title="This is !" /></p>
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('strips math in href', () => {
 | 
			
		||||
    expect( render('') ).toHtmlEqual(
 | 
			
		||||
      <p><img src="https://example.org/.png" alt="image" /></p>
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('strips math in alt text', () => {
 | 
			
		||||
    expect( render('') ).toHtmlEqual(
 | 
			
		||||
      <p><img src="https://example.org/img.png" alt="This is !" /></p>
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
describe('code', () => {
 | 
			
		||||
 | 
			
		||||
  it('highlights fenced code block', () => {
 | 
			
		||||
    // Note: We use `backticks` in this example to avoid problem that JSX
 | 
			
		||||
    // implicitly decodes HTML entities, but node-html-parser does not.
 | 
			
		||||
    expect( render('```js\nconsole.log(`Hello, world!`)\n```') ).toHtmlEqual(
 | 
			
		||||
      <pre>
 | 
			
		||||
        <code class="language-js">
 | 
			
		||||
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hello, world!`</span>)
 | 
			
		||||
        </code>
 | 
			
		||||
      </pre>
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function render (text: string) {
 | 
			
		||||
  const html = markdownRenderer(markedOpts, katexOpts)(text).replace(/\n/, '')
 | 
			
		||||
  return parseHtml(html, { pre: true }).childNodes[0]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
import { Notebook, CellType, MarkdownCell } from 'ipynb2html-core'
 | 
			
		||||
 | 
			
		||||
import readNotebookTitle from '@/readNotebookTitle'
 | 
			
		||||
 | 
			
		||||
import { Notebook, CellType, MarkdownCell } from 'ipynb2html-core'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const markdownCell = (source: string | string[]): MarkdownCell => ({
 | 
			
		||||
  cell_type: CellType.Markdown,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,5 @@
 | 
			
		|||
// This file is needed only for VSCode, see https://github.com/palmerhq/tsdx/issues/84.
 | 
			
		||||
{
 | 
			
		||||
  "extends": "../../../tsconfig.test.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "baseUrl": ".",
 | 
			
		||||
  },
 | 
			
		||||
  "references": [
 | 
			
		||||
    { "path": "../" },
 | 
			
		||||
  ],
 | 
			
		||||
  "extends": "../tsconfig.json",
 | 
			
		||||
  "include": ["."],
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,11 @@
 | 
			
		|||
    "outDir": "./lib",
 | 
			
		||||
    "tsBuildInfoFile": "./.tsbuildinfo",
 | 
			
		||||
    "baseUrl": ".",
 | 
			
		||||
    "paths": {
 | 
			
		||||
      "*": ["../../types/*"],
 | 
			
		||||
      "@/*": ["./src/*"],
 | 
			
		||||
      "~/*": ["../../*"],
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  "include": [
 | 
			
		||||
    "./src",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +0,0 @@
 | 
			
		|||
TODO: Remove after https://github.com/chrisdarroch/yarn-bump/pull/1 is merged and released.
 | 
			
		||||
 | 
			
		||||
diff --git a/node_modules/yarn-version-bump/src/workspace.js b/node_modules/yarn-version-bump/src/workspace.js
 | 
			
		||||
index 28b1dd1..0cf2ecb 100644
 | 
			
		||||
--- a/node_modules/yarn-version-bump/src/workspace.js
 | 
			
		||||
+++ b/node_modules/yarn-version-bump/src/workspace.js
 | 
			
		||||
@@ -9,7 +9,7 @@ class Workspace {
 | 
			
		||||
 
 | 
			
		||||
     get workspaceSnapshot() {
 | 
			
		||||
         return runCommand('yarn',
 | 
			
		||||
-            ['workspaces', 'info', '--silent'],
 | 
			
		||||
+            ['--silent', 'workspaces', 'info'],
 | 
			
		||||
             { cwd: this.root }
 | 
			
		||||
         )
 | 
			
		||||
         .then(data => JSON.parse(data))
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
#!/bin/sh -e
 | 
			
		||||
( set -o pipefail 2>/dev/null ) && set -o pipefail
 | 
			
		||||
 | 
			
		||||
asciidoctor -o - -b docbook "$@" | pandoc -f docbook -t markdown_github --base-header-level 2 -o -
 | 
			
		||||
asciidoctor -o - -b docbook "$@" | pandoc -f docbook -t markdown_github -o -
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,42 +0,0 @@
 | 
			
		|||
#!/usr/bin/env node
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
const fs = require('fs')
 | 
			
		||||
const path = require('path')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function extractLicenseTable (filename) {
 | 
			
		||||
  const source = fs.readFileSync(filename, 'utf8')
 | 
			
		||||
 | 
			
		||||
  const start = source.indexOf('/*!\n * Bundled npm packages')
 | 
			
		||||
  const end = start + source.slice(start).indexOf('*/')
 | 
			
		||||
 | 
			
		||||
  return source
 | 
			
		||||
    .slice(start, end)
 | 
			
		||||
    .split('\n')
 | 
			
		||||
    .filter(s => s.startsWith(' * |'))
 | 
			
		||||
    .map(s => s.slice(3))
 | 
			
		||||
    .join('\n')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function readLicense () {
 | 
			
		||||
  return fs.readFileSync(path.join(__dirname, '../LICENSE'), 'utf8')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const argv = process.argv.slice(2)
 | 
			
		||||
if (argv.length < 1 || ['-h', '--help'].includes(argv[0])) {
 | 
			
		||||
  console.warn('Usage: assemble-license <bundle-file>')
 | 
			
		||||
  process.exit(2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const bundlePath = path.resolve(argv[0])
 | 
			
		||||
 | 
			
		||||
console.log(`\
 | 
			
		||||
${readLicense()}
 | 
			
		||||
-------------------------
 | 
			
		||||
 | 
			
		||||
This product bundles source code of the following projects:
 | 
			
		||||
 | 
			
		||||
${extractLicenseTable(bundlePath)}\
 | 
			
		||||
`)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,79 +0,0 @@
 | 
			
		|||
#!/usr/bin/env node
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
const commonPathPrefix = require('common-path-prefix')
 | 
			
		||||
const execa = require('execa')
 | 
			
		||||
const fs = require('fs-extra')
 | 
			
		||||
const path = require('path')
 | 
			
		||||
const tar = require('tar')
 | 
			
		||||
const { ZipFile } = require('yazl')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async function writeTarGz (basename, fileList, cwd) {
 | 
			
		||||
  console.log(`Creating ${basename}.tar.gz...`)
 | 
			
		||||
 | 
			
		||||
  return tar.create({
 | 
			
		||||
    file: `${basename}.tar.gz`,
 | 
			
		||||
    prefix: path.basename(basename),
 | 
			
		||||
    gzip: true,
 | 
			
		||||
    portable: true,
 | 
			
		||||
    cwd: cwd || '.',
 | 
			
		||||
  }, fileList)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function writeZip (basename, fileList, cwd) {
 | 
			
		||||
  const prefix = path.basename(basename)
 | 
			
		||||
  const zipfile = new ZipFile()
 | 
			
		||||
 | 
			
		||||
  return new Promise((resolve, reject) => {
 | 
			
		||||
    console.log(`Creating ${basename}.zip...`)
 | 
			
		||||
 | 
			
		||||
    for (let fname of fileList) {
 | 
			
		||||
      zipfile.addFile(path.join(cwd || '.', fname), path.join(prefix, fname))
 | 
			
		||||
    }
 | 
			
		||||
    zipfile.outputStream
 | 
			
		||||
      .pipe(fs.createWriteStream(`${basename}.zip`))
 | 
			
		||||
      .on('close', resolve)
 | 
			
		||||
      .on('error', reject)
 | 
			
		||||
    zipfile.end()
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function gitDescribe (prefix) {
 | 
			
		||||
  const output = await execa.stdout('git', [
 | 
			
		||||
    'describe',
 | 
			
		||||
    '--always',
 | 
			
		||||
    `--match=${prefix}*`
 | 
			
		||||
  ])
 | 
			
		||||
  return output.startsWith(prefix) ? output : `v0.0.0-${output}`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function createArchives (destName, srcFiles) {
 | 
			
		||||
  const version = await gitDescribe('v')
 | 
			
		||||
  destName += `-${version}`
 | 
			
		||||
 | 
			
		||||
  const srcDir = commonPathPrefix(srcFiles)
 | 
			
		||||
  const fileList = srcFiles.map(p => p.slice(srcDir.length))
 | 
			
		||||
 | 
			
		||||
  fs.mkdirpSync(path.dirname(destName))
 | 
			
		||||
 | 
			
		||||
  return Promise.all([
 | 
			
		||||
    writeTarGz(destName, fileList, srcDir),
 | 
			
		||||
    writeZip(destName, fileList, srcDir),
 | 
			
		||||
  ])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const argv = process.argv.slice(2)
 | 
			
		||||
if (argv.length < 3 || ['-h', '--help'].includes(argv[0])) {
 | 
			
		||||
  console.warn('Usage: create-archives <dest-basename> <src-file>...')
 | 
			
		||||
  process.exit(2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const destName = argv[0]
 | 
			
		||||
const srcFiles = argv.slice(1)
 | 
			
		||||
 | 
			
		||||
createArchives(destName, srcFiles).catch(err => {
 | 
			
		||||
  console.error(err)
 | 
			
		||||
  process.exit(1)
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -1,19 +0,0 @@
 | 
			
		|||
#!/bin/sh
 | 
			
		||||
set -eu
 | 
			
		||||
 | 
			
		||||
cd "$(dirname "$0")/.."
 | 
			
		||||
 | 
			
		||||
case "${1:-}" in
 | 
			
		||||
    '' | -h | --help) echo "Usage: $0 <out-file>" >&2; exit 2;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
out_file="$1"
 | 
			
		||||
base_dir=$(basename "$(pwd)")
 | 
			
		||||
base_name=$(basename "${out_file%.tar.gz}")
 | 
			
		||||
 | 
			
		||||
mkdir -p dist
 | 
			
		||||
tar -czf "$out_file" \
 | 
			
		||||
    -C .. --exclude-vcs \
 | 
			
		||||
    --exclude="**/$out_file" \
 | 
			
		||||
    --xform="s|^$base_dir|$base_name|" \
 | 
			
		||||
    "$base_dir"
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
 | 
			
		||||
type Callable = (...args: any[]) => unknown
 | 
			
		||||
type Callable = (...args: any[]) => any
 | 
			
		||||
 | 
			
		||||
export type Mock<F extends Callable> = jest.Mock<ReturnType<F>, Parameters<F>>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,9 +13,9 @@ export function asMock <F extends Callable> (fn: F): Mock<F> {
 | 
			
		|||
export function mockResults <F extends Callable> (fn: F): Array<ReturnType<F>> {
 | 
			
		||||
  return asMock(fn).mock.results
 | 
			
		||||
    .filter(x => x.type === 'return')
 | 
			
		||||
    .map(x => x.value as ReturnType<F>)
 | 
			
		||||
    .map(x => x.value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function mockLastResult <F extends Callable> (fn: F): ReturnType<F> | undefined {
 | 
			
		||||
  return mockResults(fn).pop()
 | 
			
		||||
export function mockLastResult <F extends Callable> (fn: F): ReturnType<F> {
 | 
			
		||||
  return mockResults(fn).pop() as ReturnType<F>
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,8 +60,7 @@ export function createElement (
 | 
			
		|||
    } else if (child instanceof NNode) {
 | 
			
		||||
      el.appendChild(child)
 | 
			
		||||
    } else if (typeof child === 'object' && '__html' in child) {
 | 
			
		||||
      // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
 | 
			
		||||
      el.innerHTML = child.__html as string
 | 
			
		||||
      el.innerHTML = child.__html
 | 
			
		||||
    } else {
 | 
			
		||||
      el.appendChild(document.createTextNode(String(child)))
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -69,7 +68,6 @@ export function createElement (
 | 
			
		|||
  return el
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
 | 
			
		||||
(global as any).JSX = {
 | 
			
		||||
  createElement,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,8 +6,8 @@ type MatcherResult = jest.CustomMatcherResult
 | 
			
		|||
declare global {
 | 
			
		||||
  // eslint-disable-next-line @typescript-eslint/no-namespace
 | 
			
		||||
  namespace jest {
 | 
			
		||||
    interface Matchers<R, T> {
 | 
			
		||||
      toHtmlEqual: (expected: HTMLElement | string | Array<HTMLElement | string>) => R
 | 
			
		||||
    interface Matchers<R> {
 | 
			
		||||
      toHtmlEqual (expected: HTMLElement | string | Array<HTMLElement | string>): R,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,41 +10,33 @@ type Options = {
 | 
			
		|||
declare global {
 | 
			
		||||
  // eslint-disable-next-line @typescript-eslint/no-namespace
 | 
			
		||||
  namespace jest {
 | 
			
		||||
    interface Matchers<R, T> {
 | 
			
		||||
      toMatchElement: (expected: HTMLElement, opts?: Options) => R
 | 
			
		||||
    interface Matchers<R> {
 | 
			
		||||
      toMatchElement (expected: HTMLElement, opts?: Options): R,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const AnythingNode = new class extends Node {
 | 
			
		||||
  render () { return '<!--Anything-->' }
 | 
			
		||||
  toString () { return this.render() }
 | 
			
		||||
}()
 | 
			
		||||
 | 
			
		||||
export const Anything = (): Node => AnythingNode
 | 
			
		||||
 | 
			
		||||
function isWritable (obj: any, prop: string): boolean {
 | 
			
		||||
  const desc = Object.getOwnPropertyDescriptor(obj, prop)
 | 
			
		||||
  // eslint-disable-next-line @typescript-eslint/unbound-method
 | 
			
		||||
  return !!desc?.writable || !!desc?.set
 | 
			
		||||
}
 | 
			
		||||
export const Anything = () => AnythingNode
 | 
			
		||||
 | 
			
		||||
function filterWildcardChildren (rec: Node, exp: Node): void {
 | 
			
		||||
  if (exp.firstChild === AnythingNode
 | 
			
		||||
      && exp.childNodes.length === 1
 | 
			
		||||
      && (rec as HTMLElement).innerHTML
 | 
			
		||||
      && exp.children.length === 1
 | 
			
		||||
      && rec instanceof HTMLElement
 | 
			
		||||
      && rec.innerHTML
 | 
			
		||||
  ) {
 | 
			
		||||
    if (isWritable(rec, 'innerHTML')) {
 | 
			
		||||
      (rec as HTMLElement).innerHTML = ''
 | 
			
		||||
    }
 | 
			
		||||
    rec.childNodes.splice(0, rec.childNodes.length, AnythingNode)
 | 
			
		||||
    rec.innerHTML = ''
 | 
			
		||||
    rec.children.splice(0, rec.children.length, AnythingNode)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  for (let i = 0; i < exp.childNodes.length && i < rec.childNodes.length; i++) {
 | 
			
		||||
    if (exp.childNodes[i] === AnythingNode) {
 | 
			
		||||
      rec.childNodes[i] = AnythingNode
 | 
			
		||||
  for (let i = 0; i < exp.children.length && i < rec.children.length; i++) {
 | 
			
		||||
    if (exp.children[i] === AnythingNode) {
 | 
			
		||||
      rec.children[i] = AnythingNode
 | 
			
		||||
    } else {
 | 
			
		||||
      filterWildcardChildren(rec.childNodes[i], exp.childNodes[i])
 | 
			
		||||
      filterWildcardChildren(exp.children[i], rec.children[i])
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -54,15 +46,13 @@ function clearAttributes (node: Node): void {
 | 
			
		|||
    node.attributes = {}
 | 
			
		||||
    node.className = ''
 | 
			
		||||
  }
 | 
			
		||||
  node.childNodes.forEach(clearAttributes)
 | 
			
		||||
  node.children.forEach(clearAttributes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function toMatchElement (received: HTMLElement, expected: HTMLElement, opts?: Options): MatcherResult {
 | 
			
		||||
  if (received.cloneNode) {
 | 
			
		||||
    received = received.cloneNode(true) as HTMLElement
 | 
			
		||||
  }
 | 
			
		||||
  received = received.cloneNode(true) as HTMLElement
 | 
			
		||||
 | 
			
		||||
  if (opts?.ignoreAttrs) {
 | 
			
		||||
  if (opts && opts.ignoreAttrs) {
 | 
			
		||||
    clearAttributes(received)
 | 
			
		||||
  }
 | 
			
		||||
  filterWildcardChildren(received, expected)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "extends": "../tsconfig.test.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "baseUrl": ".",
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -42,9 +42,7 @@
 | 
			
		|||
    /* Module Resolution Options */
 | 
			
		||||
    "moduleResolution": "node",               /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
 | 
			
		||||
    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
 | 
			
		||||
    "paths": {                                /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
 | 
			
		||||
      "*": ["../../types/*"],                 /* This path is relative from baseUrl which is defined in tsconfig.json that includes this file inside each project. */
 | 
			
		||||
    },
 | 
			
		||||
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
 | 
			
		||||
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
 | 
			
		||||
    "typeRoots": [                            /* List of folders to include type definitions from. */
 | 
			
		||||
      "./types",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,5 @@
 | 
			
		|||
  "references": [
 | 
			
		||||
    { "path": "./packages/ipynb2html-core" },
 | 
			
		||||
    { "path": "./packages/ipynb2html" },
 | 
			
		||||
    { "path": "./packages/ipynb2html-cli" },
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,16 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "extends": "./tsconfig.base.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "declaration": false,
 | 
			
		||||
    "declarationMap": false,
 | 
			
		||||
    "sourceMap": false,
 | 
			
		||||
    "composite": false,
 | 
			
		||||
    "noEmit": true,
 | 
			
		||||
    "paths": {
 | 
			
		||||
      // These paths are relative from baseUrl which is defined in
 | 
			
		||||
      // tsconfig.json that includes this file inside each project.
 | 
			
		||||
      "@/*": ["../src/*"],
 | 
			
		||||
      "~/*": ["../../../*"],
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue