{"id":19329735,"url":"https://github.com/outerbounds/mdseo","last_synced_at":"2025-04-22T21:31:58.313Z","repository":{"id":39676137,"uuid":"491588967","full_name":"outerbounds/mdseo","owner":"outerbounds","description":"Analyze Markdown Documents Used In Static Sites For SEO","archived":false,"fork":false,"pushed_at":"2022-05-27T19:02:35.000Z","size":177,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-07T08:39:31.555Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://outerbounds.github.io/mdseo/","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/outerbounds.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-05-12T16:26:24.000Z","updated_at":"2022-08-18T11:03:31.000Z","dependencies_parsed_at":"2022-09-20T07:51:09.582Z","dependency_job_id":null,"html_url":"https://github.com/outerbounds/mdseo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":"fastai/nbdev_template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outerbounds%2Fmdseo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outerbounds%2Fmdseo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outerbounds%2Fmdseo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outerbounds%2Fmdseo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/outerbounds","download_url":"https://codeload.github.com/outerbounds/mdseo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250328581,"owners_count":21412642,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-10T02:29:43.796Z","updated_at":"2025-04-22T21:31:58.041Z","avatar_url":"https://github.com/outerbounds.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mdseo\n\u003e Analyze Markdown Documents Used In Static Sites For SEO\n\n\n[![CI](https://github.com/outerbounds/mdseo/actions/workflows/main.yml/badge.svg)](https://github.com/outerbounds/mdseo/actions/workflows/main.yml)\n [![](https://img.shields.io/pypi/v/nbdoc)](https://pypi.org/project/mdseo/)\n[![](https://img.shields.io/static/v1?label=fastai\u0026message=nbdev\u0026color=57aeac\u0026labelColor=black\u0026style=flat\u0026logo=data:image/png;base64,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)](https://github.com/fastai/nbdev)\n\n## Table of Contents\n\n\n- [Installation](#installation)\n- [Usage](#usage)\n- [Examples](#examples)\n- [Ignoring Checks](#ignoring-checks)\n    - [With Front Matter](#with-front-matter)\n    - [With The Keyword `mdseo-ignore-all`](#with-the-keyword-mdseo-ignore-all)\n\n\n## Installation\n\n\u003e pip install mdseo\n\n## Usage\n\n`mdseo` provides CLI tools to check various statistics and metadata in markdown files.  If an unwanted property is discovered, and error is raised.  An overview of the CLI tools are below:\n\n```python\n!mdseo_dupe_title -h\n```\n\n    usage: mdseo_dupe_title [-h] [--srcdir SRCDIR]\n    \n    Check for duplicate titles. Ignore with front matter `mdseo-ignore:\n    [dupe_title]`\n    \n    optional arguments:\n      -h, --help       show this help message and exit\n      --srcdir SRCDIR  directory of files to check (default: .)\n\n\n```python\n!mdseo_len -h\n```\n\n    usage: mdseo_len [-h] [--n N] [--srcdir SRCDIR]\n    \n    Check if docs contain less than `n` words. Ignore with front matter `mdseo-\n    ignore: [length]`\n    \n    optional arguments:\n      -h, --help       show this help message and exit\n      --n N            minimum number of words a document should contain (default:\n                       50)\n      --srcdir SRCDIR  directory of files to check (default: .)\n\n\n```python\n!mdseo_chk_fm -h\n```\n\n    usage: mdseo_chk_fm [-h] [--srcdir SRCDIR] [--minlen MINLEN] [--maxlen MAXLEN]\n                        {description,slug,image,authors}\n    \n    Check front matter for various rules.\n    \n    positional arguments:\n      {description,slug,image,authors}  front matter field to check\n    \n    optional arguments:\n      -h, --help                        show this help message and exit\n      --srcdir SRCDIR                   directory of files to check (default: .)\n      --minlen MINLEN                   the minimum character length allowed for the\n                                        field\n      --maxlen MAXLEN                   the maximum character length allowed for the\n                                        field\n\n\n## Examples\n\n**Check that `description` is between 50 and 300 characters:**\n\n```python\n!mdseo_chk_fm description --minlen 50 --maxlen 300\n```\n\n    Traceback (most recent call last):\n      File \"/Users/hamel/opt/anaconda3/bin/mdseo_chk_fm\", line 33, in \u003cmodule\u003e\n        sys.exit(load_entry_point('mdseo', 'console_scripts', 'mdseo_chk_fm')())\n      File \"/Users/hamel/github/fastcore/fastcore/script.py\", line 113, in _f\n        tfunc(**merge(args, args_from_prog(func, xtra)))\n      File \"/Users/hamel/github/mdseo/mdseo/core.py\", line 101, in chk_fm\n        return _checker(partial(_min_len_err, key=key, n=minlen),\n      File \"/Users/hamel/github/mdseo/mdseo/core.py\", line 89, in _checker\n        if fnames: raise Exception(f\"The following files {msg}:\\n\\t{files}\")\n    Exception: The following files have the field `description` in their front matter that is less than 50 characters:\n    \t./test_files/front_matter3.md\n\n\n**Check that the front matter `slug` exists:**\n\n```python\n!mdseo_chk_fm slug\n```\n\n    Traceback (most recent call last):\n      File \"/Users/hamel/opt/anaconda3/bin/mdseo_chk_fm\", line 33, in \u003cmodule\u003e\n        sys.exit(load_entry_point('mdseo', 'console_scripts', 'mdseo_chk_fm')())\n      File \"/Users/hamel/github/fastcore/fastcore/script.py\", line 113, in _f\n        tfunc(**merge(args, args_from_prog(func, xtra)))\n      File \"/Users/hamel/github/mdseo/mdseo/core.py\", line 107, in chk_fm\n        _checker(partial(_missing_fm, key=key), f\"do not have the field `{key}` in their front matter\", srcdir)\n      File \"/Users/hamel/github/mdseo/mdseo/core.py\", line 89, in _checker\n        if fnames: raise Exception(f\"The following files {msg}:\\n\\t{files}\")\n    Exception: The following files do not have the field `slug` in their front matter:\n    \t./CONTRIBUTING.md\n    \t./test_files/false_fm2.md\n    \t./test_files/false_fm.md\n    \t./test_files/test_docs.md\n\n\n**Check that the front matter `slug` is no longer than 45 characters:**\n\n```python\n!mdseo_chk_fm slug --maxlen 45\n```\n\n    Traceback (most recent call last):\n      File \"/Users/hamel/opt/anaconda3/bin/mdseo_chk_fm\", line 33, in \u003cmodule\u003e\n        sys.exit(load_entry_point('mdseo', 'console_scripts', 'mdseo_chk_fm')())\n      File \"/Users/hamel/github/fastcore/fastcore/script.py\", line 113, in _f\n        tfunc(**merge(args, args_from_prog(func, xtra)))\n      File \"/Users/hamel/github/mdseo/mdseo/core.py\", line 104, in chk_fm\n        return _checker(partial(_max_len_err, key=key, n=maxlen),\n      File \"/Users/hamel/github/mdseo/mdseo/core.py\", line 89, in _checker\n        if fnames: raise Exception(f\"The following files {msg}:\\n\\t{files}\")\n    Exception: The following files have the field `slug` in their front matter that is greater than 45 characters:\n    \t./test_files/front_matter_test_docs.md\n\n\n**Check that the front matter `authors` exists:**\n\n```python\n!mdseo_chk_fm authors\n```\n\n    Traceback (most recent call last):\n      File \"/Users/hamel/opt/anaconda3/bin/mdseo_chk_fm\", line 33, in \u003cmodule\u003e\n        sys.exit(load_entry_point('mdseo', 'console_scripts', 'mdseo_chk_fm')())\n      File \"/Users/hamel/github/fastcore/fastcore/script.py\", line 113, in _f\n        tfunc(**merge(args, args_from_prog(func, xtra)))\n      File \"/Users/hamel/github/mdseo/mdseo/core.py\", line 107, in chk_fm\n        _checker(partial(_missing_fm, key=key), f\"do not have the field `{key}` in their front matter\", srcdir)\n      File \"/Users/hamel/github/mdseo/mdseo/core.py\", line 89, in _checker\n        if fnames: raise Exception(f\"The following files {msg}:\\n\\t{files}\")\n    Exception: The following files do not have the field `authors` in their front matter:\n    \t./CONTRIBUTING.md\n    \t./test_files/front_matter2.md\n    \t./test_files/false_fm2.md\n    \t./test_files/front_matter_test_docs.md\n    \t./test_files/false_fm.md\n    \t./test_files/test_docs.md\n\n\n## Ignoring Checks\n\nYou may wish to ignore checks on individual files, there are two ways to do this (1) Through a special front-matter field called `mdseo-ignore` or (2) by placing the word `mdseo-ignore-all` in your markdown file.\n\n### With Front Matter\n\nTo ignore a check via front matter, supply the proper value(s) in the `mdseo-ignore` field in your front matter.  For example, if you wanted to ignore the `mdseo_dupe_title` and `mdseo_image` checks in a particular markdown file, you would inject the following front matter:\n\n```\n---\nmdseo-ignore: [dupe_title, image]\n---\n```\n\nYou can find these values by consulting the help of the appropriate cli command, for example `mdseo_dupe_title -h` says:\n\n```\n... Ignore with front matter `mdseo-ignore:[dupe_title]`\n```\n\nIf you want to ignore all seo rules, you can also pass `all` like so:\n\n```\n---\nmdseo-ignore: all\n---\n```\n\nThere is a generic function `mdseo_chk_fm` that checks the presence, min length and max length of a front matter field.  You can ignore any checks conducted by this function by passing in the appropriate fields to `mdseo-ignore`.  These are the fields that you can ignore:\n\n\n\n\n`description`, `slug`, `image`, `authors`\n\n\n\nFor example, if you wanted to ingore all of these fields you could put the following in your front matter:\n\n\n\n\n```\n---\nmdseo-ignore: [description,slug,image,authors]\n---\n```\n\n\n\n\n### With The Keyword `mdseo-ignore-all`\n\nSome markdown files may not have front matter, or it may not be appropriate to add front matter to a file.  In this case you can place the text `mdseo-ignore-all` anywhere in the file and all checks will be ignored, the most common way to add this keyword is with a markdown comment:\n\n```\n\u003c-- mdseo-ignore-all --\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fouterbounds%2Fmdseo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fouterbounds%2Fmdseo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fouterbounds%2Fmdseo/lists"}