Metadata-Version: 2.4
Name: ndx
Version: 0.6.0
Summary: Build annotated index file for a directory.
Author: M. Farzalipour Tabriz
License-Expression: GPL-3.0-or-later
License-File: LICENSES/GPL-3.0-or-later.txt
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: POSIX
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
Requires-Dist: google-re2>=1.1.20251105
Requires-Dist: jsonschema>=4.26.0
Requires-Dist: nh3>=0.3.7
Requires-Python: >=3.10, <3.15
Project-URL: source, https://gitlab.mpcdf.mpg.de/tbz/ndx.git
Description-Content-Type: text/x-rst

***
ndx
***
A static HTML directory index generator.

``ndx`` is a command-line utility for generating index files for directories. It supports file annotations via a JSON configuration file.

Installation
############
.. code-block:: shell

    pipx install ndx

Usage
#####
To generate an index in a specific directory, use:

.. code-block:: shell

    ndx /path/to/directory

Generate index files recursively:

.. code-block:: shell

    ndx --recursive /path/to/directory

Options
*******
.. code-block:: shell

    usage: ndx [-h] [-r] [--explicit] [--max-depth MAX_DEPTH] [--max-files MAX_FILES] [--timeout TIMEOUT] [-f] [-v] [--version]
            directory

    Builds index for directories. Annotates the index with data from .ndx.json file.

    positional arguments:
    directory             path to the target directory

    options:
    -h, --help            show this help message and exit
    -r, --recursive       build index files recursively (default: False)
    --explicit            explicitly link to index.html files when linking to directories (default: False)
    --max-depth MAX_DEPTH
                            maximum recursion depth (levels below the target directory) for building index files (default: 50)
    --max-files MAX_FILES
                            maximum number of entries to process for each index (default: 10000)
    --timeout TIMEOUT     timeout for symlink stat and path resolution while processing files for the index (in seconds) (default:
                            10)
    -f, --force           overwrite existing index.html file(s) (default: False)
    -v, --verbose         enable verbose logging (default: False)
    --version             show program's version number and exit

Configuration
#############

To customize the index by adding descriptions to the page and files, place a ``.ndx.json`` file in the target directory. In recursive mode, each subdirectory needs its own ``.ndx.json`` file.

Schema
******

.. code-block:: json

    {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "object",
        "properties": {
            "page": {
                "type": "object",
                "properties": {
                    "description": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 10000
                    }
                },
                "required": ["description"],
                "additionalProperties": false
            },
            "files": {
                "type": "array",
                "minItems": 1,
                "maxItems": 10000,
                "items": {
                    "type": "object",
                    "properties": {
                        "name_regex": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 200,
                            "format": "re2-pattern"
                        },
                        "description": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 1000
                        },
                    },
                    "required": ["name_regex", "description"],
                    "additionalProperties": false
                }
            }
        },
        "required": ["page"],
        "additionalProperties": false
    }

Examples
********

.. code-block:: json

    {
      "page": {
        "description": "Index page with minimal config file (no file-level description)."
      }
    }

.. code-block:: json

    {
        "page": {
        "description": "Index page with description and a <a href='https://example.com'>link</a>."
        },
        "files": [
        {
            "name_regex": ".*\\.pdf$",
            "description": "File descriptions can also have <a href='https://example.com'>links</a>"
        },
        {
            "name_regex": "\\.tar",
            "description": "Regex patterns do not need to match the full file name. For example, this description will be applied to both *.tar and *.tar.gz files."
        }
        ]
    }

Design Choices and Limitations
##############################
- Script is only tested with currently supported Python versions.
- Functionality is only guaranteed on POSIX-compliant Unix-like systems.
- The target directory can be passed to this script via a symlink.
- Support for hardlinks on the filesystem containing the target directory is required unless the ``--force`` option is used.
- The index files may lose their former ownership and attributes when regenerated.
- Hidden files (starting with ``.``) and the index file ``index.html`` are skipped.
- Symlinks pointing outside the directory [or subdirectory] being indexed are skipped.
- Special files (FIFOs, sockets, devices) are skipped.
- If there are more than ``--max-files`` in a directory to process, only ``--max-files`` entries in filesystem enumeration order are processed to prevent resource exhaustion.
- ``.ndx.json`` file cannot be a symlink.
- ``.ndx.json`` file size is limited to a maximum of 1M (1,048,576) characters.
- In recursive mode, each subdirectory needs its own ``.ndx.json`` file.
- Only `RE2 regexes <https://github.com/google/re2/wiki/Syntax>`_ are supported.
- A warning is issued and notes are skipped for files that match multiple regexes.
- If ``.ndx.json`` file does not conform to the schema, it is completely ignored.
- Descriptions only support HTML anchor tags (``<a href=''>...</a>``).
- Only HTTPS links are supported in the descriptions.
- All attributes except the ``href`` are stripped from the HTML anchor tags, and ``target="_blank" rel="noopener noreferrer nofollow"`` is added to them.
- Malformed HTML descriptions may lose some of their content during processing.
- If the output file is not created for any reason, such as permission errors, exceeding the recursion depth limit, or the existence of an index file, the script exits with a non-zero status code.
- Failure to access file attributes for indexing is logged, but it has no effect on the script exit code.

History
#######
This script was originally developed for the `linkmedic <https://pypi.org/project/linkmedic/>`_ project.

License
#######
* Copyright 2025-2026 M. Farzalipour Tabriz, Max Planck Institute for Physics (MPP)

All rights reserved.

This software may be modified and distributed under the terms of the GPL-3.0 (or later) License. See the ``LICENSE`` file for details.
