npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@onozaty/growi-uploader

v1.7.1

Published

A content uploader for GROWI

Readme

growi-uploader

Test codecov npm version License: MIT

English | 日本語

A CLI tool to batch upload local Markdown files and attachments to GROWI Wiki.

Features

  • 📁 Preserves directory structure - Local folder hierarchy becomes GROWI page hierarchy
  • 📝 Markdown file upload - Creates or updates GROWI pages from .md files
  • 📎 Automatic attachment detection - Files matching <page>_attachment_<file> pattern are uploaded as attachments
  • 🔗 Link replacement - Automatically converts local attachment links to GROWI format (/attachment/{id})
  • 🖼️ Image embedding - Supports image links (![alt](image.png)) with automatic conversion
  • ⚙️ Flexible configuration - Control base path, update behavior, and more

Quick Start

  1. Create a configuration file growi-uploader.json:
{
  "url": "https://your-growi-instance.com",
  "token": "your-api-token",
  "basePath": "/",
  "update": false
}
  1. Run with npx (no installation required):
npx @onozaty/growi-uploader ./docs

That's it! Your local ./docs directory will be uploaded to GROWI.

Installation

Using npx (Recommended)

No installation required. Just run:

npx @onozaty/growi-uploader <source-dir>

Global Installation

For frequent use, you can install globally:

npm install -g @onozaty/growi-uploader
growi-uploader <source-dir>

Usage

Basic Command

growi-uploader <source-dir> [options]

Arguments:

  • <source-dir>: Path to the directory containing Markdown files

Options:

  • -c, --config <path>: Path to config file (default: growi-uploader.json)
  • -v, --verbose: Enable verbose error output with detailed information
  • -V, --version: Output the version number
  • -h, --help: Display help information

Examples

# Upload with default config file
npx @onozaty/growi-uploader ./docs

# Upload with custom config file
npx @onozaty/growi-uploader ./docs -c my-config.json

# Upload with verbose error output
npx @onozaty/growi-uploader ./docs --verbose

Directory Structure Example

Local Directory

docs/
  guide.md
  guide_attachment_diagram.svg
  guide_attachment_sample.txt
  api/
    overview.md
    overview_attachment_example.json
    authentication.md

Resulting GROWI Pages

/docs/guide                    (from guide.md)
  └─ diagram.svg               (attachment)
  └─ sample.txt                (attachment)
/docs/api/overview             (from api/overview.md)
  └─ example.json              (attachment)
/docs/api/authentication       (from api/authentication.md)

Page Name Normalization

To prevent API errors, page names are automatically normalized using the following rules:

Normalization Rules

  1. Spaces around slashes → Replaced with underscores

    • a / b.md/a_/_b
  2. Special characters → Replaced with safe alternatives:

    • +-plus-
    • ?-question-
    • *-asterisk-
    • $-dollar-
    • ^-caret-
    • %-percent-
  3. Reserved page names → Suffixed with underscore:

    • editedit_ (only when it's the last path segment)

Examples

Local file                     GROWI page path
──────────────────────────────────────────────────
C++.md                      →  /C-plus--plus-
What?.md                    →  /What-question-
C++ / Python?.md            →  /C-plus--plus-_/_Python-question-
edit.md                     →  /edit_
docs/edit.md                →  /docs/edit_
docs/normal-page.md         →  /docs/normal-page (no change)

This normalization ensures compatibility with GROWI's page naming requirements while preserving the readability of your file names.

Configuration File

Create a growi-uploader.json file in your project root:

{
  "url": "https://your-growi-instance.com",
  "token": "your-api-token",
  "basePath": "/imported",
  "update": true,
  "verbose": false
}

Configuration Options

| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| | url | string | ✅ | - | GROWI instance URL | | token | string | ✅ | - | GROWI API access token | | basePath | string | ❌ | / | Base path for imported pages | | update | boolean | ❌ | false | Update existing pages if true, skip if false | | verbose | boolean | ❌ | false | Enable verbose error output with detailed information |

Getting an API Token

  1. Log in to your GROWI instance
  2. Go to User SettingsAPI Settings
  3. Click Issue new token
  4. Copy the generated token to your config file

Attachment Files

Attachments are automatically detected using two methods:

Method 1: Naming Convention

Files following this naming pattern are detected as attachments:

<page-name>_attachment_<filename>

Example:

guide.md                       → GROWI page: /guide
guide_attachment_image.png     → Attached to /guide
guide_attachment_document.pdf  → Attached to /guide

Method 2: Link-Based Detection

Files referenced in markdown links are automatically detected as attachments:

Local Directory:

guide.md
assets/
  banner.png
images/
  logo.png
  screenshot.png

guide.md Content:

![Logo](./images/logo.png)
![Screenshot](images/screenshot.png)
![Banner](/assets/banner.png)

All referenced files (logo.png, screenshot.png, and banner.png) will be uploaded as attachments to the /guide page, even though they don't follow the _attachment_ naming convention.

Path resolution:

  • Markdown escape sequences are unescaped (\(()
  • URL encoding (percent-encoding) is decoded (%20 → space, %E7%94%BB%E5%83%8F画像)
  • Relative paths (./, ../, or no prefix): Resolved from the Markdown file's directory
  • Absolute paths (starting with /): Resolved from the source directory root
    • Example: /assets/banner.png<source-dir>/assets/banner.png

Supported link formats:

![Logo](./images/logo.png)                # Standard relative path
![Logo](images/logo.png)                  # Relative path without ./
![Image](./images/%E7%94%BB%E5%83%8F.png) # URL-encoded Japanese filename
[File](./docs/my%20file.pdf)              # URL-encoded space
[File](<./path/file (1).png>)             # Special chars with angle brackets
![Image](./path/file\\(1\\).png)          # Special chars with escaping
<img src="./images/logo.png" alt="Logo">  # HTML img tag (double quotes)
<img src='./images/logo.png' alt='Logo'>  # HTML img tag (single quotes)

Excluded from detection:

  • .md files (treated as page links)
  • External URLs (http://, https://)
  • Non-existent files

Automatic Link Replacement

Markdown links to attachments are automatically converted to GROWI format (/attachment/{id}).

Example (Naming Convention):

# Before upload
![Diagram](./guide_attachment_diagram.png)
Download the [documentation](guide_attachment_document.pdf).

# After upload (on GROWI)
![Diagram](/attachment/68f3a41c794f665ad2c0d322)
Download the [documentation](/attachment/68f3a3fa794f665ad2c0d2b3).

Example (Link-Based):

# Before upload
![Logo](./images/logo.png)

# After upload (on GROWI)
![Logo](/attachment/68f3a41c794f665ad2c0d322)

Both detection methods support multiple link formats (with or without ./).

Cross-Page References

When a file following the naming convention (BBB_attachment_*) is referenced from a different page (AAA.md):

  • The attachment is uploaded only to its owner page (/BBB)
  • Links in the referencing page (AAA.md) are replaced with the attachment URL (/attachment/{id})

Example:

File structure:
  AAA.md (contains: ![](BBB_attachment_image.png))
  BBB.md
  BBB_attachment_image.png

Result:
  - BBB_attachment_image.png is uploaded to /BBB page only
  - The link in AAA.md is replaced with /attachment/{id}

Page Link Conversion

Links to other Markdown files (.md extension) are automatically converted to GROWI format.

Supported Patterns

# Before upload (local)
[User Guide](./guide.md)
[API Overview](../api/overview.md)
[Auth Section](./api/auth.md#setup)

# After upload (on GROWI)
[User Guide](./guide)
[API Overview](../api/overview)
[Auth Section](./api/auth#setup)
  • The .md extension is removed
  • Relative path prefixes (./, ../) are preserved (GROWI supports relative links)
  • Anchor links (#section) are preserved
  • External URLs (http://, https://) are not modified

Advanced Usage

Update Existing Pages

Set update: true in your config file to update existing pages:

{
  "url": "https://your-growi-instance.com",
  "token": "your-api-token",
  "update": true
}

Import to Specific Path

Use basePath to import all pages under a specific path:

{
  "url": "https://your-growi-instance.com",
  "token": "your-api-token",
  "basePath": "/imported"
}

Result:

docs/guide.md  →  /imported/docs/guide

Output Example

Found 5 Markdown file(s) and 3 attachment(s)

[SUCCESS] docs/guide.md → /docs/guide (created)
[SUCCESS] docs/guide_attachment_diagram.svg → /docs/guide (attachment)
[SUCCESS] docs/guide.md → /docs/guide (attachment links replaced)
[SUCCESS] docs/api/overview.md → /docs/api/overview (created)
[SKIP] docs/api/auth.md → /docs/api/auth (page already exists)

Completed:
- Pages created: 2
- Pages updated: 0
- Pages skipped: 1
- Page errors: 0
- Attachments uploaded: 2
- Attachments skipped: 0
- Attachment errors: 0
- Link replacement errors: 0

Requirements

  • Node.js 18 or later
  • GROWI instance with REST API v3 support

License

MIT

Author

onozaty