Repository: folke/lazy.nvim
File: lua/lazy/help.lua (Lua)

Code before:
local Config = require("lazy.core.config")
local Util = require("lazy.util")

local M = {}

function M.index(plugin)
  if Config.options.readme.skip_if_doc_exists and vim.loop.fs_stat(plugin.dir .. "/doc") then
    return {}
  end
  local files = vim.tbl_flatten(vim.tbl_map(function(file)
    return vim.fn.expand(plugin.dir .. "/" .. file, false, true)
  end, Config.options.readme.files))
  ---@type table<string,{file:string, tag:string, line:string}>
  local tags = {}
  for _, file in ipairs(files) do
    if vim.loop.fs_stat(file) then
      local tag_filename = plugin.name
      if file:find("lua/") then
        local rel_file = file:gsub(plugin.dir .. "/", "")
        tag_filename = plugin.name .. vim.fn.fnamemodify(rel_file, ":h:s?lua??:gs?/?-?")
      end
      local lines = vim.split(Util.read_file(file), "\n")
      for _, line in ipairs(lines) do
        local title = line:match("^#+%s*(.*)")
        if title then
          local tag = tag_filename .. "-" .. title:lower():gsub("%W+", "-")
          tag = tag:gsub("%-+", "-"):gsub("%-$", "")
          line = line:gsub("([%[%]/])", "\\%1")
          tags[tag] = { tag = tag, line = line, file = tag_filename .. ".md" }
        end
      end
      table.insert(lines, [[<!-- vim: set ft=markdown: -->]])
      Util.write_file(Config.options.readme.root .. "/doc/" .. tag_filename .. ".md", table.concat(lines, "\n"))
    end
  end
  return tags
end

function M.update()
  vim.cmd.helptags(Config.plugins["lazy.nvim"].dir .. "/doc")
  local docs = Config.options.readme.root .. "/doc"
  vim.fn.mkdir(docs, "p")


Review comment (suggestion):
Would be better to make this more general. So build the filename based on everything after `plugin.dir`. So for example:

`nui.nvim/lua/nui/popup/README.md` -> `nui.nvim-lua-nui-popup`

Code after:
local Config = require("lazy.core.config")
local Util = require("lazy.util")

local M = {}

function M.index(plugin)
  if Config.options.readme.skip_if_doc_exists and vim.loop.fs_stat(plugin.dir .. "/doc") then
    return {}
  end
  local files = vim.tbl_flatten(vim.tbl_map(function(file)
    return vim.fn.expand(plugin.dir .. "/" .. file, false, true)
  end, Config.options.readme.files))
  ---@type table<string,{file:string, tag:string, line:string}>
  local tags = {}
  for _, file in ipairs(files) do
    file = Util.norm(file)
    if vim.loop.fs_stat(file) then
      local rel_file = file:sub(#plugin.dir + 1)
      local tag_filename = string.gsub(plugin.name .. vim.fn.fnamemodify(rel_file, ":h:gs?/?-?"), "-$", "")
      local lines = vim.split(Util.read_file(file), "\n")
      for _, line in ipairs(lines) do
        local title = line:match("^#+%s*(.*)")
        if title then
          local tag = tag_filename .. "-" .. title:lower():gsub("%W+", "-")
          tag = tag:gsub("%-+", "-"):gsub("%-$", "")
          line = line:gsub("([%[%]/])", "\\%1")
          tags[tag] = { tag = tag, line = line, file = tag_filename .. ".md" }
        end
      end
      table.insert(lines, [[<!-- vim: set ft=markdown: -->]])
      Util.write_file(Config.options.readme.root .. "/doc/" .. tag_filename .. ".md", table.concat(lines, "\n"))
    end
  end
  return tags
end

function M.update()
  vim.cmd.helptags(Config.plugins["lazy.nvim"].dir .. "/doc")
  local docs = Config.options.readme.root .. "/doc"
  vim.fn.mkdir(docs, "p")

  Util.ls(docs, function(path, name, type)
    if type == "file" and name:sub(-2) == "md" then