GithubHelp home page GithubHelp logo

adrienbrignon / mkdocs-exporter Goto Github PK

View Code? Open in Web Editor NEW
63.0 6.0 0.0 1.5 MB

๐Ÿ“ MkDocs Exporter is a powerful plugin for MkDocs that enables seamless conversion of single pages and/or the entire documentation into professional PDF files.

Home Page: https://adrienbrignon.github.io/mkdocs-exporter/

License: MIT License

Python 83.35% SCSS 2.67% Jinja 6.40% Dockerfile 2.10% Makefile 1.61% CSS 0.55% HTML 0.42% JavaScript 2.91%
mkdocs pdf mkdocs-plugin markdown pdf-generation mkdocs-plugins documentation mkdocs-print

mkdocs-exporter's Introduction

Hi, I'm Adrien

I work as CTO at Lunarr and Cesarr.

Monthly statistics

mkdocs-exporter's People

Contributors

adrienbrignon avatar oprypin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

mkdocs-exporter's Issues

playwright._impl._api_types.TimeoutError: Timeout 30000ms exceeded.

Hi, @adrienbrignon,

As per your suggestion given in Issue #3, I tried with ubuntu image and the playwright installation finally went fine. Now I see the below timeout issue. Please verify and suggest if any config changes can be done for the plugin to avoid this issue,

File "/usr/local/bin/mkdocs", line 8, in
sys.exit(cli())
^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1130, in call
return self.main(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1055, in main
rv = self.invoke(ctx)
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1657, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1404, in invoke
return ctx.invoke(self.callback, **ctx.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 760, in invoke
return __callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/mkdocs/main.py", line 250, in build_command
build.build(cfg, dirty=not clean)
File "/usr/local/lib/python3.11/dist-packages/mkdocs/commands/build.py", line 332, in build
config.plugins.run_event('post_build', config=config)
File "/usr/local/lib/python3.11/dist-packages/mkdocs/plugins.py", line 522, in run_event
result = method(**kwargs)
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/mkdocs_exporter/plugins/pdf/plugin.py", line 152, in on_post_build
self.loop.run_until_complete(asyncio.gather(*concurrently(self.tasks, max(1, self.config.concurrency or 1))))
File "/usr/local/lib/python3.11/dist-packages/nest_asyncio.py", line 90, in run_until_complete
return f.result()
^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/tasks.py", line 269, in __step
result = coro.throw(exc)
^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/mkdocs_exporter/plugins/pdf/plugin.py", line 148, in limit
return await asyncio.create_task(coroutine)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/futures.py", line 287, in await
yield self # This tells Task to wait for completion.
^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/tasks.py", line 339, in __wakeup
future.result()
File "/usr/lib/python3.11/asyncio/futures.py", line 203, in result
raise self._exception.with_traceback(self._exception_tb)
File "/usr/lib/python3.11/asyncio/tasks.py", line 267, in __step
result = coro.send(None)
^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/mkdocs_exporter/plugins/pdf/plugin.py", line 122, in render
pdf = await self.renderer.render(page)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/mkdocs_exporter/plugins/pdf/renderer.py", line 76, in render
return await self.browser.print(html)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/mkdocs_exporter/plugins/pdf/browser.py", line 91, in print
await page.locator('.pagedjs_pages').wait_for(timeout=30000)
File "/usr/local/lib/python3.11/dist-packages/playwright/async_api/_generated.py", line 18010, in wait_for
await self._impl_obj.wait_for(timeout=timeout, state=state)
File "/usr/local/lib/python3.11/dist-packages/playwright/_impl/_locator.py", line 662, in wait_for
await self._frame.wait_for_selector(
File "/usr/local/lib/python3.11/dist-packages/playwright/_impl/_frame.py", line 322, in wait_for_selector
await self._channel.send("waitForSelector", locals_to_params(locals()))
File "/usr/local/lib/python3.11/dist-packages/playwright/_impl/_connection.py", line 61, in send
return await self._connection.wrap_api_call(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/playwright/_impl/_connection.py", line 482, in wrap_api_call
return await cb()
^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/playwright/_impl/_connection.py", line 97, in inner_send
result = next(iter(done)).result()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/futures.py", line 203, in result
raise self._exception.with_traceback(self._exception_tb)
playwright._impl._api_types.TimeoutError: Timeout 30000ms exceeded.
=========================== logs ===========================
waiting for locator(".pagedjs_pages") to be visible

I see from some online forums this issue can be fixed if we can increase or disable the timeout value, (timeout = 0).

File "/usr/local/lib/python3.11/dist-packages/mkdocs_exporter/plugins/pdf/browser.py", line 91, in print
await page.locator('.pagedjs_pages').wait_for(timeout=30000)

Please share your thoughts.
Thanks

Unable to get the plugin to work with MKDocs (Material theme)

Issue

Plugin seems unable to generate PDFs

Description

I've installed the plugin using pip, at first run it asked me to update Playwright, so I did. Trying to start the dev server again I got the following error:

Log

Running mkdocs serve gives this output:

INFO     -  Building documentation...
INFO     -  Cleaning site directory
INFO     -  The following pages exist in the docs directory, but are not included in the "nav" configuration:
              - index.md
              - hei.md
              - MicroBit\index.md
              - MicroBit\introduksjontilMicrobit.md
              - Testing\index.md
WARNING  -  A relative path to 'index.html' is included in the 'nav' configuration, which is not found in the documentation files
WARNING  -  A relative path to 'MicroBit/index.html' is included in the 'nav' configuration, which is not found in the documentation files
INFO     -  Rendering PDF for index.md...
INFO     -  Launching browser...
INFO     -  Rendering PDF for MicroBit\index.md...
Traceback (most recent call last):
  File "C:\Program Files\Python310\lib\runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Program Files\Python310\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\mkdocs\__main__.py", line 301, in <module>
    cli()
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\click\core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\click\core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\click\core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\click\core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\click\core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\mkdocs\__main__.py", line 234, in serve_command
    serve.serve(dev_addr=dev_addr, livereload=livereload, watch=watch, **kwargs)
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\mkdocs\commands\serve.py", line 83, in serve
    builder(config)
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\mkdocs\commands\serve.py", line 76, in builder
    build(config, live_server=live_server, dirty=dirty)
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\mkdocs\commands\build.py", line 332, in build
    config.plugins.run_event('post_build', config=config)
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\mkdocs\plugins.py", line 522, in run_event
    result = method(**kwargs)
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\mkdocs_exporter\plugins\pdf\plugin.py", line 143, in on_post_build
    loop.run_until_complete(asyncio.gather(*concurrently(self.tasks, max(1, self.config.concurrency or 1))))
  File "C:\Program Files\Python310\lib\asyncio\base_events.py", line 646, in run_until_complete
    return future.result()
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\mkdocs_exporter\plugins\pdf\plugin.py", line 137, in limit
    return await asyncio.create_task(coroutine)
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\mkdocs_exporter\plugins\pdf\plugin.py", line 113, in render
    pdf = await self.renderer.render(page, polyfills=self.config['polyfills'])
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\mkdocs_exporter\plugins\pdf\renderer.py", line 79, in render
    return await self.browser.print(html)
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\mkdocs_exporter\browser.py", line 81, in print
    await page.goto('file://' + file.name, wait_until='networkidle')
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\playwright\async_api\_generated.py", line 9204, in goto
    await self._impl_obj.goto(
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\playwright\_impl\_page.py", line 495, in goto
    return await self._main_frame.goto(**locals_to_params(locals()))
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\playwright\_impl\_frame.py", line 147, in goto
    await self._channel.send("goto", locals_to_params(locals()))
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\playwright\_impl\_connection.py", line 61, in send
    return await self._connection.wrap_api_call(
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\playwright\_impl\_connection.py", line 461, in wrap_api_call
    return await cb()
  File "C:\Users\tor30122\AppData\Roaming\Python\Python310\site-packages\playwright\_impl\_connection.py", line 96, in inner_send
    result = next(iter(done)).result()
playwright._impl._api_types.Error: net::ERR_FAILED at file:///C:/Users/tor30122/AppData/Local/Temp/tmpdm_awifw.html
=========================== logs ===========================
navigating to "file:///C:/Users/tor30122/AppData/Local/Temp/tmpdm_awifw.html", waiting until "networkidle"
============================================================

Configuration

My mkdocs.yml file is:

site_name: IM Boka

nav:
    - Velkommen: 'index.html'
    - MicroBit: 'MicroBit/index.html'

theme:
  name: material
  language: nb
  features:
    - navigation.instant
    - navigation.tracking
    - navigation.tabs
#    - navigation.expand
#    - navigation.indexes
#    - navigation.footer
    - content.code.copy

  palette:
    # Palette toggle for light mode
    - scheme: default
      primary: teal
      toggle:
        icon: material/lightbulb
        name: Switch to dark mode

    # Palette toggle for dark mode
    - scheme: slate
      primary: teal
      toggle:
        icon: material/lightbulb-outline
        name: Switch to light mode
        primary: teal

extra:
  consent:
    title: Cookie consent
    description: >-
      We use cookies to recognize your repeated visits and preferences, as well
      as to measure the effectiveness of our documentation and whether users
      find what they're searching for. With your consent, you're helping us to
      make our documentation better.
    actions:
      - accept
      - reject

copyright: >
  Copyright &copy; 2023 IM Greveskogen โ€“
  <a href="#__consent">Endre cookie innstillinger</a>

plugins:
  - search
  - offline
  - mkdocs-video
  - mkdocs/exporter
  - mkdocs/exporter/pdf
    
markdown_extensions:
  - attr_list
  - pymdownx.emoji:
      emoji_index: !!python/name:materialx.emoji.twemoji
      emoji_generator: !!python/name:materialx.emoji.to_svg 
  - pymdownx.highlight:
      anchor_linenums: true
  - pymdownx.superfences:
      custom_fences:
        - name: mermaid
          class: mermaid
          format: !!python/name:pymdownx.superfences.fence_code_format
  - pymdownx.tabbed:
      alternate_style: true 
  - admonition
  - pymdownx.details

Correct macro use

Hello,
I was trying to get you example template to fill in the jinja2 fields but I never could. I made sure mkdocs-macros was installed and I was able to load the config test just fine on my home page with {{ macros_info() }}

When creating the PDFs I get no errors, and the resulting PDF looks perfect, except the field are still just the field {{ whatever }}.

I feel like there's some config I'm missing but I'm at a loss. Any idea where to look next?

Other then that thanks so much for this extension. Makes a beautiful PDF!

Installing with pip ends up with an error (ModuleNotFoundError: No module named '_ctypes')

Tried to install with pip and python3.10 on debian linux

 File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
    File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
    File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
    File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
    File "<frozen importlib._bootstrap_external>", line 883, in exec_module
    File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
    File "/tmp/pip-build-env-r85rh432/normal/lib/python3.10/site-packages/wheel/bdist_wheel.py", line 27, in <module>
      from .macosx_libfile import calculate_macosx_platform_tag
    File "/tmp/pip-build-env-r85rh432/normal/lib/python3.10/site-packages/wheel/macosx_libfile.py", line 43, in <module>
      import ctypes
    File "/usr/local/lib/python3.10/ctypes/__init__.py", line 8, in <module>
      from _ctypes import Union, Structure, Array
  ModuleNotFoundError: No module named '_ctypes'

Config value 'plugins': Invalid config options for the 'mkdocs/exporter' plugin.

Hi @adrienbrignon,

Hope you remember me, I worked with you for a get_evet_loop issue few weeks back.
I upgraded the plugin version to 3.0.3 and I was using the same mkdocs file given below, I'm receiving the "invalid config" error, please let me know if any other plugin configurations I have to add here in the file,

plugins:
  mkdocs/exporter:
    theme:'material'
  mkdocs/exporter/pdf:
    concurrency: 8
    covers:
      front: resources/templates/covers/front.html.j2
      back: resources/templates/covers/back.html.j2
    stylesheets:
      - resources/stylesheets/pdf.scss
  mkdocs/exporter/extras:
    buttons:
      - title: Download as PDF
        enabled: !!python/name:mkdocs_exporter.plugins.pdf.button.enabled
        icon: !!python/name:mkdocs_exporter.plugins.pdf.button.icon
        attributes:
          href: !!python/name:mkdocs_exporter.plugins.pdf.button.href
          download: !!python/name:mkdocs_exporter.plugins.pdf.button.download

ERROR - Config value 'plugins': Invalid config options for the 'mkdocs/exporter' plugin.
Aborted with 1 Configuration Errors!

Thanks

The way of taking icons will be deprecated, making it impossible to build in strict mode

Hello everyone.

using the mkdocs build --strict --verbose MkDocs command's is impossible to build for the way MkDocs exporter uses emoji. in fact i get this warning

INFO    -  DeprecationWarning: 'materialx.emoji.to_svg' is deprecated.
 Material emoji logic has been officially moved into mkdocs-material
version 9.4. Please use Material's 'material.extensions.emoji.to_svg'
instead of 'materialx.emoji.to_svg' in your 'mkdocs.yml' file.

markdown_extensions:
- pymdownx.emoji:
       emoji_index: !!python/name:material.extensions.emoji.twemoji
       emoji_generator: !!python/name:material.extensions.emoji.to_svg

mkdocs_material_extensions' is deprecated and will no longer be
supported moving forward. This is the last release.

   File "/usr/local/lib/python3.10/dist-packages/mkdocs_exporter/themes/material/icons.py", line 35, in get_icon
     icon = to_svg('twemoji', name, None, None, None, None, None, {}, Markdown())
   File "/usr/local/lib/python3.10/dist-packages/materialx/emoji.py", line 68, in _deprecated_func
    warnings.warn(

 WARNING -  Material emoji logic has been officially moved into mkdocs-material
 version 9.4. Please use Material's 'material.extensions.emoji.to_svg'
 instead of 'materialx.emoji.to_svg' in your 'mkdocs.yml' file.

 markdown_extensions:
  - pymdownx.emoji:
       emoji_index: !!python/name:material.extensions.emoji.twemoji
       emoji_generator: !!python/name:material.extensions.emoji.to_svg

mkdocs_material_extensions' is deprecated and will no longer be supported moving forward. This is the last release.

And it end with Aborted with 1 warnings in strict mode!
So the problem is in /themes/material/icons.py.

Thank you for reading me!

EDIT:
the new library syntax should be from material.extensions.emoji import twemoji, to_svg

Idea: use mkdocs-print-page to print all website

I see in the roadmap:

Combine all pages as one PDF

And I know that mkdocs-print-site does one thing: automatically create a page served at /print_page that combine all pages of the site.

I thought I just had to combine your plugins and the print-site one to have a neat pdf of all my documentation.

This failed with a playwright._impl._errors.TimeoutError :( If you ever get curious, you can find the full traceback in this gist.

So I was wondering if you were aware of this print-site-plugin. Anyway, you may want to handle this feature by yourself to get more control of the process.

RuntimeError: There is no current event loop in thread 'MainThread'.

Hi,

I have recently switched from mkdocs-with-pdf plugin to your plugin, first I would like to thank you for the contribution.
The below error message is not allowing to proceed further,

File "/usr/local/lib/python3.11/site-packages/mkdocs_exporter/plugins/pdf/plugin.py", line 141, in on_post_build
loop = asyncio.get_event_loop()
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/events.py", line 677, in get_event_loop
raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'MainThread'.

Could you please check on this one and kindly support to resolve the issue.

Config for covers behaviour in aggregator not working

The functionality to configure which covers should be included in the aggregated pdf as described in #22 is missing. The configuration for the feature is still referenced in the Usage section of the README and in the mkdocs.yml of this project.

As #22 describes, this would have had the following options:

  • all (default): will include all cover pages
  • none: will exclude all cover pages
  • limits: will include only the front cover of the first page and the back cover of the last page

The configuration does not seem to be possible anymore and is no longer referenced anywhere in the actual code:

class AggregatorConfig(BaseConfig):

I really like the feature of aggregating all sites into one and would love to be able to only have one of the front and back cover each.

UnicodeDecodeError: gbk - Illegal Multibyte Sequence

Traceback (most recent call last):
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\Scripts\mkdocs.exe\__main__.py", line 7, in <module>
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\click\core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\click\core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\click\core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\click\core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\click\core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\mkdocs\__main__.py", line 234, in serve_command
    serve.serve(dev_addr=dev_addr, livereload=livereload, watch=watch, **kwargs)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\mkdocs\commands\serve.py", line 83, in serve
    builder(config)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\mkdocs\commands\serve.py", line 76, in builder
    build(config, live_server=live_server, dirty=dirty)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\mkdocs\commands\build.py", line 332, in build
    config.plugins.run_event('post_build', config=config)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\mkdocs\plugins.py", line 522, in run_event
    result = method(**kwargs)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\mkdocs_exporter\plugins\pdf\plugin.py", line 151, in on_post_build
    self.loop.run_until_complete(asyncio.gather(*concurrently(self.tasks, max(1, self.config.concurrency or 1))))
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\nest_asyncio.py", line 90, in run_until_complete
    return f.result()
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\asyncio\tasks.py", line 258, in __step
    result = coro.throw(exc)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\mkdocs_exporter\plugins\pdf\plugin.py", line 147, in limit
    return await asyncio.create_task(coroutine)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\asyncio\futures.py", line 284, in __await__
    yield self  # This tells Task to wait for completion.
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\asyncio\tasks.py", line 328, in __wakeup
    future.result()
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\asyncio\futures.py", line 201, in result
    raise self._exception
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\asyncio\tasks.py", line 256, in __step
    result = coro.send(None)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\mkdocs_exporter\plugins\pdf\plugin.py", line 122, in render
    html = self.renderer.preprocess(page)
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\site-packages\mkdocs_exporter\plugins\pdf\renderer.py", line 69, in preprocess
    preprocessor.script(importlib_resources.files(js).joinpath('pagedjs.min.js').read_text())
  File "C:\Users\chenxianrui\AppData\Local\Programs\Python\Python39\lib\pathlib.py", line 1267, in read_text
    return f.read()
UnicodeDecodeError: 'gbk' codec can't decode byte 0xbd in position 6267: illegal multibyte sequence

This error typically occurs when there is an issue with decoding a byte sequence using the 'gbk' codec, which is a character encoding commonly used for simplified Chinese text. It suggests that there might be a problem with the content of the file being processed, possibly due to an encoding mismatch or an invalid multibyte sequence.

I have followed the instruction and installed the prerequisite and when I run the "mkdocs serve", the error msg is above.

Code blocks with custom titles: titles are separated from the body

hi there, thanks a bunch for the plugin โ€” it works very well for my use case (โ—'โ—ก'โ—)

my issue is exactly as the title says, titles of custom titled code blocks are separated from the body of the code block. this would lead to some jarring whitespace when the code blocks contain long streams of text โ€” leaving the title of the code block on the page before

  • pdf:

    image

  • website:

    image

  • code:

    image

is this intended behaviour?

Rendering pages with MathJax as PDF

I have a document I'm trying to render as PDF including LaTeX text, but the PDF only shows the raw LaTeX commands. MathJax is configured like here. I feel like this should work already considering this uses a browser to render the page, though. Do I need something else to make this work?

Issues with font kerning on headless chromium + fix

as seen in puppeteer/puppeteer#2410

  • running mkdocs serve on windows:

    image

  • running mkdocs build on linux:

    image

  • running mkdocs build on linux with --font-render-hinting=none:

    image

  • running mkdocs serve, and viewing it on a browser:

    image

while the windows and the 'fixed' linux pdf do still have kerning difference, looking at the woes of the people before us (https://www.google.com/search?q=bad+font+kerning+on+headless+chrome), this would be considered 'the bare minimum' to fix glaring inconsistent typography issues

the fix for this, as per the issue, would be to add --font-render-hinting=none to the args of chromium in mkdocs_exporter/formats/pdf/browser.py:

diff --git a/formats/pdf/browser.py b/formats/pdf/browser-kerning-fix.py
index b5cd103..2109c25 100644
--- a/formats/pdf/browser.py
+++ b/formats/pdf/browser-kerning-fix.py
@@ -15,7 +15,8 @@ class Browser:
   args = [
     '--disable-background-timer-throttling',
     '--disable-renderer-backgrounding',
-    '--allow-file-access-from-files'
+    '--allow-file-access-from-files',
+    '--font-render-hinting=none',
   ]
   """The browser's arguments..."""

once again, thanks for the project :)

Render relative links with a `project_url` setting

Hello,
First of all, I would like to thank you for your work. I was desperate to find a maintained plugin achieving mkdocs -> pdf export.

At the moment, the relatives links are not rendered in pdf. Maybe we could add a project_url optional setting where users could set their root url allowing us to render relatives links.

For instance, say we have somewhere a link toward ../assets/folder/file.txt on documentation page docs/exemple.md hosted at http://mydoc.com/exemple/.

I would set project_url : http://mydoc.com in mkdocs.yml and, in the pdf, the link would direct toward http://mydocs.com/assets/folder/file.txt

I hope my explanations makes some kind of sense.
Thanks again for your work!

Automatically create a table of contents from headers in generated PDF

Hello

I am wondering if it is possible to automatically generate a table of contents (TOC) when a PDF is created based off of the headers in the markdown file that is being converted to PDF?

If not, would this be something considered as an enhancement to the plugin?

Thank you!

FEATURE REQUEST - drawio support

Hey,

Thanks for creating such a useful mkdocs plugin. I really like your work!
As you mentioned on the Repositories README, I would like to request an additional feature:

Currently, I'm using a plugin for embedding drawio diagrams into mkdocs (More Information about the Plugin). Basically, the plugin simplifies the workflow of embedding a diagram by allowing to embed the .drawio file directly instead of exporting the diagram to a .svg and embed this.
I tried to export PDFs with your exporter, which works perfectly fine, but I wasn't able to export a site with the drawio Diagram. There was no Error and the export works, the diagram just wasn't showing in the exported PDF.
So my guess was that this is just not supported by your plugin.

I would be very happy if you could include this feature. Feel free to contact me about further questions or if I can be of assistance.

The `mkdocs-exporter` pypi library fails to install into the latest, official `mkdocs-material` Docker container image

This issue from the microsoft/playwright-python project appears to be related.

TL;DR: Since mkdocs-exporter relies on playwright and (as of 2024-06-20) it does not provide install instructions or a package for Alpine, without deep diving into what Alpine system-level dependencies are required (and if they are even available via official Alpine repos), there is no way to install mkdocs-exporter into Alpine-based docker images. Those that attempt an install will receive playwright related errors below. Unfortunately, the offical mkdocs-material, is Alpine based at this time. So a supported theme (material) is only available to mkdocs-exporter+mkdocs-material users if they manually install mkdocs-material and mkdocs-exporter onto a playwright supported OS (like Debian). This issue provides a sample Dockerfile that does exactly this and works as of 2024-06-20 with the current latest versions of mkdocs-material, mkdocs-exporter, and the playwright Pypi packages; however, it would be great if mkdocs-exporter developers could figure out how to allow for Alpine based installs or (at a mimimum) advertise that they do not support Alpine-based deployments.

Expected Behavior

Given I attempt to install mkdocs-exporter into the official, latest docker.io/squidfunk/mkdocs-material:9.5.27 (v9.5.27 at the time of this bug report) Docker container image like so,

FROM docker.io/squidfunk/mkdocs-material:9.5.27
RUN pip install mkdocs-exporter

as described by the official mkdocs-material documentation for installing additional python plugin libraries,

When I execute a docker build command, like so,

 docker build -t mkdocs-material-with-exporter .

Then the Docker container image builds successfully and mkdocs-exporter functions as described in the documentation when using it to export mkdocs sites as PDFs.

Observed Behavior

Given I attempt to install mkdocs-exporter into the official, latest docker.io/squidfunk/mkdocs-material:9.5.27 (v9.5.27 at the time of this bug report) Docker container image like so,

FROM docker.io/squidfunk/mkdocs-material:9.5.27
RUN pip install mkdocs-exporter

as described by the official mkdocs-material documentation for installing additional python plugin libraries,

When I execute a docker build command, like so,

 docker build -t mkdocs-material-with-exporter .

Then the Docker container image fails to build, and provides the following error messages:

[+] Building 5.5s (6/6) FINISHED                                                                      docker:default
 => [internal] load build definition from Dockerfile                                                            0.0s
 => => transferring dockerfile: 117B                                                                            0.0s
 => [internal] load metadata for docker.io/squidfunk/mkdocs-material:9.5.27                                     0.5s
 => [auth] squidfunk/mkdocs-material:pull token for registry-1.docker.io                                        0.0s
 => [internal] load .dockerignore                                                                               0.0s
 => => transferring context: 2B                                                                                 0.0s
 => CACHED [1/2] FROM docker.io/squidfunk/mkdocs-material:9.5.27@sha256:257eca88da7f42242cd05e8cebf6d10ebd079e  0.0s
 => ERROR [2/2] RUN pip install mkdocs-exporter                                                                 4.9s
------                                                                                                               
 > [2/2] RUN pip install mkdocs-exporter:                                                                            
1.554 Collecting mkdocs-exporter                                                                                     
1.635   Downloading mkdocs_exporter-6.0.0-py3-none-any.whl.metadata (5.5 kB)                                         
1.752 Collecting beautifulsoup4>=4.12.2 (from mkdocs-exporter)                                                       
1.766   Downloading beautifulsoup4-4.12.3-py3-none-any.whl.metadata (3.8 kB)                                         
1.998 Collecting libsass>=0.22.0 (from mkdocs-exporter)
2.010   Downloading libsass-0.23.0.tar.gz (316 kB)
2.077      โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” 316.1/316.1 kB 5.3 MB/s eta 0:00:00
2.119   Preparing metadata (setup.py): started
2.740   Preparing metadata (setup.py): finished with status 'done'
3.005 Collecting lxml>=4.9 (from mkdocs-exporter)
3.019   Downloading lxml-5.2.2-cp311-cp311-musllinux_1_2_x86_64.whl.metadata (3.4 kB)
3.028 Requirement already satisfied: mkdocs>=1.4 in /usr/local/lib/python3.11/site-packages (from mkdocs-exporter) (1.6.0)
3.114 INFO: pip is looking at multiple versions of mkdocs-exporter to determine which version is compatible with other requirements. This could take a while.
3.114 Collecting mkdocs-exporter
3.127   Downloading mkdocs_exporter-5.3.1-py3-none-any.whl.metadata (5.8 kB)
3.243 Collecting importlib-metadata>=6.0 (from mkdocs-exporter)
3.258   Downloading importlib_metadata-7.1.0-py3-none-any.whl.metadata (4.7 kB)
3.355 Collecting importlib-resources>=5.0 (from mkdocs-exporter)
3.367   Downloading importlib_resources-6.4.0-py3-none-any.whl.metadata (3.9 kB)
3.377 Requirement already satisfied: mkdocs-material<10.0.0,>=9.4.14 in /usr/local/lib/python3.11/site-packages (from mkdocs-material[imaging]<10.0.0,>=9.4.14->mkdocs-exporter) (9.5.27)
3.456 Collecting nest-asyncio>=1.5.6 (from mkdocs-exporter)
3.469   Downloading nest_asyncio-1.6.0-py3-none-any.whl.metadata (2.8 kB)
3.480 Collecting mkdocs-exporter
3.495   Downloading mkdocs_exporter-5.3.0-py3-none-any.whl.metadata (5.8 kB)
3.536   Downloading mkdocs_exporter-5.2.1-py3-none-any.whl.metadata (5.6 kB)
3.567   Downloading mkdocs_exporter-5.2.0-py3-none-any.whl.metadata (5.6 kB)
3.602   Downloading mkdocs_exporter-5.1.0-py3-none-any.whl.metadata (5.4 kB)
3.637   Downloading mkdocs_exporter-5.0.0-py3-none-any.whl.metadata (5.4 kB)
3.669   Downloading mkdocs_exporter-4.1.0-py3-none-any.whl.metadata (5.4 kB)
3.694 Collecting importlib-metadata<5.0 (from mkdocs-exporter)
3.706   Downloading importlib_metadata-4.13.0-py3-none-any.whl.metadata (4.9 kB)
3.717 INFO: pip is still looking at multiple versions of mkdocs-exporter to determine which version is compatible with other requirements. This could take a while.
3.718 Collecting mkdocs-exporter
3.731   Downloading mkdocs_exporter-4.0.2-py3-none-any.whl.metadata (5.4 kB)
3.766   Downloading mkdocs_exporter-4.0.1-py3-none-any.whl.metadata (5.4 kB)
3.809   Downloading mkdocs_exporter-4.0.0-py3-none-any.whl.metadata (5.4 kB)
3.846   Downloading mkdocs_exporter-3.1.1-py3-none-any.whl.metadata (5.4 kB)
3.881   Downloading mkdocs_exporter-3.1.0-py3-none-any.whl.metadata (5.4 kB)
3.899 INFO: This is taking longer than usual. You might need to provide the dependency resolver with stricter constraints to reduce runtime. See https://pip.pypa.io/warnings/backtracking for guidance. If you want to abort this run, press Ctrl + C.
3.915   Downloading mkdocs_exporter-3.0.3-py3-none-any.whl.metadata (5.4 kB)
3.956   Downloading mkdocs_exporter-3.0.2-py3-none-any.whl.metadata (5.4 kB)
3.993   Downloading mkdocs_exporter-3.0.1-py3-none-any.whl.metadata (5.4 kB)
4.034   Downloading mkdocs_exporter-3.0.0-py3-none-any.whl.metadata (5.4 kB)
4.079   Downloading mkdocs_exporter-2.0.2-py3-none-any.whl.metadata (5.4 kB)
4.122   Downloading mkdocs_exporter-2.0.1-py3-none-any.whl.metadata (4.7 kB)
4.168   Downloading mkdocs_exporter-2.0.0-py3-none-any.whl.metadata (4.6 kB)
4.197   Downloading mkdocs_exporter-1.3.0-py3-none-any.whl.metadata (4.7 kB)
4.216 Requirement already satisfied: mkdocs-material-extensions<2.0.0,>=1.1.1 in /usr/local/lib/python3.11/site-packages (from mkdocs-exporter) (1.3.1)
4.231   Downloading mkdocs_exporter-1.2.2-py3-none-any.whl.metadata (4.4 kB)
4.264   Downloading mkdocs_exporter-1.2.1-py3-none-any.whl.metadata (4.4 kB)
4.302   Downloading mkdocs_exporter-1.2.0-py3-none-any.whl.metadata (4.4 kB)
4.345   Downloading mkdocs_exporter-1.1.0-py3-none-any.whl.metadata (4.5 kB)
4.386   Downloading mkdocs_exporter-1.0.2-py3-none-any.whl.metadata (4.4 kB)
4.420   Downloading mkdocs_exporter-1.0.1-py3-none-any.whl.metadata (4.1 kB)
4.454   Downloading mkdocs_exporter-1.0.0-py3-none-any.whl.metadata (4.0 kB)
4.490   Downloading mkdocs_exporter-0.0.2-py3-none-any.whl.metadata (4.0 kB)
4.521   Downloading mkdocs_exporter-0.0.1-py3-none-any.whl.metadata (1.4 kB)
4.534 ERROR: Cannot install mkdocs-exporter==0.0.1, mkdocs-exporter==0.0.2, mkdocs-exporter==1.0.0, mkdocs-exporter==1.0.1, mkdocs-exporter==1.0.2, mkdocs-exporter==1.1.0, mkdocs-exporter==1.2.0, mkdocs-exporter==1.2.1, mkdocs-exporter==1.2.2, mkdocs-exporter==1.3.0, mkdocs-exporter==2.0.0, mkdocs-exporter==2.0.1, mkdocs-exporter==2.0.2, mkdocs-exporter==3.0.0, mkdocs-exporter==3.0.1, mkdocs-exporter==3.0.2, mkdocs-exporter==3.0.3, mkdocs-exporter==3.1.0, mkdocs-exporter==3.1.1, mkdocs-exporter==4.0.0, mkdocs-exporter==4.0.1, mkdocs-exporter==4.0.2, mkdocs-exporter==4.1.0, mkdocs-exporter==5.0.0, mkdocs-exporter==5.1.0, mkdocs-exporter==5.2.0, mkdocs-exporter==5.2.1, mkdocs-exporter==5.3.0, mkdocs-exporter==5.3.1 and mkdocs-exporter==6.0.0 because these package versions have conflicting dependencies.
4.534 
4.534 The conflict is caused by:
4.534     mkdocs-exporter 6.0.0 depends on playwright>=1.33
4.534     mkdocs-exporter 5.3.1 depends on playwright>=1.33
4.534     mkdocs-exporter 5.3.0 depends on playwright>=1.33
4.534     mkdocs-exporter 5.2.1 depends on playwright>=1.33
4.534     mkdocs-exporter 5.2.0 depends on playwright>=1.33
4.534     mkdocs-exporter 5.1.0 depends on playwright>=1.33
4.534     mkdocs-exporter 5.0.0 depends on playwright>=1.33
4.534     mkdocs-exporter 4.1.0 depends on playwright>=1.33
4.534     mkdocs-exporter 4.0.2 depends on playwright>=1.33
4.534     mkdocs-exporter 4.0.1 depends on playwright>=1.33
4.534     mkdocs-exporter 4.0.0 depends on playwright>=1.33
4.534     mkdocs-exporter 3.1.1 depends on playwright>=1.33
4.534     mkdocs-exporter 3.1.0 depends on playwright>=1.33
4.534     mkdocs-exporter 3.0.3 depends on playwright>=1.33
4.534     mkdocs-exporter 3.0.2 depends on playwright>=1.33
4.534     mkdocs-exporter 3.0.1 depends on playwright>=1.33
4.534     mkdocs-exporter 3.0.0 depends on playwright>=1.33
4.534     mkdocs-exporter 2.0.2 depends on playwright>=1.33
4.534     mkdocs-exporter 2.0.1 depends on playwright>=1.33
4.534     mkdocs-exporter 2.0.0 depends on playwright>=1.33
4.534     mkdocs-exporter 1.3.0 depends on playwright>=1.33
4.534     mkdocs-exporter 1.2.2 depends on playwright>=1.33
4.534     mkdocs-exporter 1.2.1 depends on playwright>=1.33
4.534     mkdocs-exporter 1.2.0 depends on playwright>=1.33
4.534     mkdocs-exporter 1.1.0 depends on playwright>=1.33
4.534     mkdocs-exporter 1.0.2 depends on playwright>=1.33
4.534     mkdocs-exporter 1.0.1 depends on playwright>=1.33
4.534     mkdocs-exporter 1.0.0 depends on playwright>=1.33
4.534     mkdocs-exporter 0.0.2 depends on playwright>=1.33
4.534     mkdocs-exporter 0.0.1 depends on playwright>=1.33
4.534 
4.534 To fix this you could try to:
4.534 1. loosen the range of package versions you've specified
4.534 2. remove package versions to allow pip attempt to solve the dependency conflict
4.534 
4.535 ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/latest/topics/dependency-resolution/#dealing-with-dependency-conflicts
------
Dockerfile:2
--------------------
   1 |     FROM docker.io/squidfunk/mkdocs-material:9.5.27
   2 | >>> RUN pip install mkdocs-exporter
   3 |     
--------------------
ERROR: failed to solve: process "/bin/sh -c pip install mkdocs-exporter" did not complete successfully: exit code: 1

Additional Notes

Running pip --debug install mkdocs-exporter on the RUN line of the Dockerfile yields a more robust error message with colorized output. I have not provided that here due to the length of the output, the custom formatting that will likely get mangled, and how easily reproducible it is on a developer's local machine.

I have attempted this same install procedure with downgraded versions of both the Docker container image and the mkdocs-exporter library, so I suspect it has been an issue for a while.

I have attempted explicitly installing playwright via pip install playwright inside the container and experienced similar errors.

$ docker run --rm -it --entrypoint '' docker.io/squidfunk/mkdocs-material:9.5.27 /bin/sh
/docs # pip install playwright
ERROR: Could not find a version that satisfies the requirement playwright (from versions: none)
ERROR: No matching distribution found for playwright

Attempting to install older versions of playwright explicitly (playwright==1.33.0, for example) yields the same results.

The docker.io/squidfunk/mkdocs-material:9.5.27 image uses Alpine 3.19.1, which is still supported by the Alpine team until 2025-05-09.

It looks like playwright is not installable on the upstream vanilla Alpine image either based on this test:

$ docker run --rm -it --entrypoint '' docker.io/alpine:3.19.1 /bin/sh
# apk add python3
# apk add py3-pip
# pip install --break-system-packages playwright

However, it has no issues on this Debian-based image:

$ docker run --rm -it --entrypoint '' docker.io/python:3-bookworm /bin/sh
# pip install playwright

I was able to get mkdocs-exporter working by translating the official mkdocs-material Dockerfile to a functionally equivalent Debian-based one, but that solution is not exactly ideal. For anyone else trying to solve this same issue in the interim, here is the Dockerfile:

FROM python:3.11-bookworm

# Build-time flags
ARG WITH_PLUGINS=true

# Environment variables
ENV PACKAGES=/usr/local/lib/python3.11/site-packages
ENV PYTHONDONTWRITEBYTECODE=1

# Set build directory
WORKDIR /tmp

# Copy files necessary for build
COPY mkdocs-material/material material
COPY mkdocs-material/package.json package.json
COPY mkdocs-material/README.md README.md
COPY mkdocs-material/*requirements.txt ./
COPY *requirements.txt ./
COPY mkdocs-material/pyproject.toml pyproject.toml

# Perform build and cleanup artifacts and caches
RUN \
  apt update \
&& \
  apt install -y \
    libcairo2-dev \
    libfreetype-dev \
    git \
    libjpeg-dev \
    openssh-client \
    tini \
    zlib1g-dev \
&& \
  apt install -v \
    gcc \
    libffi-dev \
&& \
  pip install --no-cache-dir --upgrade pip \
&& \
  if [ "${WITH_PLUGINS}" = "true" ]; then \
    pip install --no-cache-dir \
      mkdocs-material[recommended] \
      mkdocs-material[imaging] \
      mkdocs-exporter \
      mkdocs-macros-plugin; \
  fi \
&& \
  for theme in mkdocs readthedocs; do \
    rm -rf ${PACKAGES}/mkdocs/themes/$theme; \
    ln -s \
      ${PACKAGES}/material/templates \
      ${PACKAGES}/mkdocs/themes/$theme; \
  done \
&& \
  playwright install \
&& \
  playwright install-deps \
&& \
  find ${PACKAGES} \
    -type f \
    -path "*/__pycache__/*" \
    -exec rm -f {} \; \
&& \
  git config --system --add safe.directory /docs \
&& \
  git config --system --add safe.directory /site

# Set working directory
WORKDIR /docs

# Expose MkDocs development server port
EXPOSE 8000

# Start development server by default
ENTRYPOINT ["/usr/bin/tini", "--", "mkdocs"]
CMD ["serve", "--dev-addr=0.0.0.0:8000"]

Note: size-wise, this is nowhere as close to as slim as the Alpine-based image provided by squidfunk/mkdocs-material, and I am sure there is more refinement that can be done to make it slimmer, but it works (as of v9.5.27 of mkdocs-material). Here is the original Dockerfile that this one is based on. This Dockerfile assumes that you have done a git clone of squidfunk/mkdocs-material from Github and that repository is in a subdirectory relative to this Dockerfile.

The biggest differences between this Dockerfile and the official one from mkdocs-material are:

  • Debian vs Alpine based, so FROM line is different and apt is used instead of apk for system pkg installs
  • Equivalent package names are different (some are not required) on Debian vs Alpine
  • tini is installed in a different directory so the ENTRYPOINT is different
  • Cannot remove the .cache directory because this is where PDFs are cached post-build
  • Removed the user-requirements.txt install lines and hardcoded the install of libraries like mkdocs-exporter
  • Not clearing the package manager cache or removing build deps after system pkg installs

RuntimeError

I am removing the details of this issue as I discovered I needed to use a newer version of Python on my end. I will close the issue.

Not work ?

Hello,

i tried to install your package on my readthedocs repository, but unfortunately it didn't work...
and I don't see a "Download button" (same after adding the part)

The readme is also difficult to understand since there is no "back" file somewhere in the repository
and same if I only add the "front" I have multiple python error
There is also no information about how PDF are generated (during what process ? mkdocs serve? mkdocs build) and where to have it.

Into my mkdocs.yml file,

my python version: 3.8 / mkdocs: the latest

Regards

Use different color scheme to export PDFs

Suggestion: add a flag that lets users select certain color scheme

For instance, my site defaults to the slate (dark theme) but ideally I'd like the PDF exporter to use the default (light) theme in generating documents

theme:
  palette:
    # - media: "(prefers-color-scheme: dark)"
    - scheme: slate
      accent: amber
      toggle:
        icon: material/brightness-2
        name: "Switch to light mode"
    # - media: "(prefers-color-scheme: light)"
    - scheme: default
      accent: deep purple
      toggle:
        icon: material/brightness-5
        name: "Switch to dark mode"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.