Subiendo api v2
This commit is contained in:
0
deps/logger_file_backend/.fetch
vendored
Normal file
0
deps/logger_file_backend/.fetch
vendored
Normal file
BIN
deps/logger_file_backend/.hex
vendored
Normal file
BIN
deps/logger_file_backend/.hex
vendored
Normal file
Binary file not shown.
40
deps/logger_file_backend/CHANGELOG.md
vendored
Normal file
40
deps/logger_file_backend/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## v0.0.14
|
||||
|
||||
- fix warnings about the use of deprecated :warn
|
||||
- Bumps versions of `credo` and `ex_doc` to latest
|
||||
|
||||
## v0.0.13
|
||||
|
||||
- Docs cleanup
|
||||
- Release file handle
|
||||
- Bumps versions of `credo` and `ex_doc` to latest
|
||||
|
||||
## v0.0.12 - 2021-07-19
|
||||
|
||||
- Bumps dependency versions
|
||||
- Combing through documentation
|
||||
|
||||
## v0.0.11 - 2019-08-06
|
||||
|
||||
### Enhancements
|
||||
|
||||
- Add simple strategy to rotate log files ([3a4d7f](https://github.com/mstratman/logger_file_backend/commit/3a4d7ffea4fd1ea4f4ba2629051efc259dd668ec))
|
||||
- Allow :all in :metadata option ([#54](https://github.com/onkel-dirtus/logger_file_backend/pull/54))
|
||||
|
||||
### Fixes
|
||||
|
||||
- Documentation fix ([#39](https://github.com/onkel-dirtus/logger_file_backend/pull/39))
|
||||
- Eliminate warnings ([#30](https://github.com/onkel-dirtus/logger_file_backend/pull/30), [361c7d](https://github.com/mstratman/logger_file_backend/commit/361c7d81cb408a8aee824d080e16fd26f1920621), [1f0390](https://github.com/mstratman/logger_file_backend/commit/1f0390b29fe90516bd4b70d82250de065900fd41), [#43](https://github.com/onkel-dirtus/logger_file_backend/pull/43))
|
||||
|
||||
### Changes
|
||||
|
||||
- Update dependencies ([#30](https://github.com/onkel-dirtus/logger_file_backend/pull/30))
|
||||
21
deps/logger_file_backend/LICENSE.md
vendored
Normal file
21
deps/logger_file_backend/LICENSE.md
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Kurt Williams
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
163
deps/logger_file_backend/README.md
vendored
Normal file
163
deps/logger_file_backend/README.md
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
# LoggerFileBackend
|
||||
|
||||
[](https://hex.pm/packages/logger_file_backend)
|
||||
[](https://hexdocs.pm/logger_file_backend/)
|
||||
[](https://hex.pm/packages/logger_file_backend)
|
||||
[](https://github.com/onkel-dirtus/logger_file_backend/blob/master/LICENSE.md)
|
||||
[](https://github.com/onkel-dirtus/logger_file_backend/commits/master)
|
||||
|
||||
A simple Elixir `Logger` backend which writes logs to a file. It does not handle log rotation, but it does tolerate log file renames, so it can be used in conjunction with external log rotation.
|
||||
|
||||
**Note** The renaming of log files does not work on Windows, because `File.Stat.inode` is used to determine whether the log file has been (re)moved and, on non-Unix, `File.Stat.inode` is always 0.
|
||||
|
||||
**Note** If you are running this with the Phoenix framework, please review the Phoenix specific instructions later on in this file.
|
||||
|
||||
## Configuration
|
||||
|
||||
`LoggerFileBackend` is a custom backend for the elixir `:logger` application. As
|
||||
such, it relies on the `:logger` application to start the relevant processes.
|
||||
However, unlike the default `:console` backend, we may want to configure
|
||||
multiple log files, each with different log levels, formats, etc. Also, we want
|
||||
`:logger` to be responsible for starting and stopping each of our logging
|
||||
processes for us. Because of these considerations, there must be one `:logger`
|
||||
backend configured for each log file we need. Each backend has a name like
|
||||
`{LoggerFileBackend, id}`, where `id` is any elixir term (usually an atom).
|
||||
|
||||
For example, let's say we want to log error messages to
|
||||
`"/var/log/my_app/error.log"`. To do that, we will need to configure a backend.
|
||||
Let's call it `{LoggerFileBackend, :error_log}`.
|
||||
|
||||
Our `config.exs` would have an entry similar to this:
|
||||
|
||||
```elixir
|
||||
# tell logger to load a LoggerFileBackend processes
|
||||
config :logger,
|
||||
backends: [{LoggerFileBackend, :error_log}]
|
||||
```
|
||||
|
||||
With this configuration, the `:logger` application will start one `LoggerFileBackend`
|
||||
named `{LoggerFileBackend, :error_log}`. We still need to set the correct file
|
||||
path and log levels for the backend, though. To do that, we add another config
|
||||
stanza. Together with the stanza above, we'll have something like this:
|
||||
|
||||
```elixir
|
||||
# tell logger to load a LoggerFileBackend processes
|
||||
config :logger,
|
||||
backends: [{LoggerFileBackend, :error_log}]
|
||||
|
||||
# configuration for the {LoggerFileBackend, :error_log} backend
|
||||
config :logger, :error_log,
|
||||
path: "/var/log/my_app/error.log",
|
||||
level: :error
|
||||
```
|
||||
|
||||
Check out the examples below for runtime configuration and configuration for
|
||||
multiple log files.
|
||||
|
||||
`LoggerFileBackend` supports the following configuration values:
|
||||
|
||||
* `path` - the path to the log file
|
||||
* `level` - the logging level for the backend
|
||||
* `format` - the logging format for the backend
|
||||
* `metadata` - the metadata to include
|
||||
* `metadata_filter` - metadata terms which must be present in order to log
|
||||
* metadata_reject - metadata terms which must be present in order to do not log
|
||||
|
||||
### Examples
|
||||
|
||||
#### Runtime configuration
|
||||
|
||||
```elixir
|
||||
Logger.add_backend {LoggerFileBackend, :debug}
|
||||
Logger.configure_backend {LoggerFileBackend, :debug},
|
||||
path: "/path/to/debug.log",
|
||||
format: ...,
|
||||
metadata: ...,
|
||||
metadata_filter: ...
|
||||
```
|
||||
|
||||
#### Application config for multiple log files
|
||||
|
||||
```elixir
|
||||
config :logger,
|
||||
backends: [{LoggerFileBackend, :info},
|
||||
{LoggerFileBackend, :error}]
|
||||
|
||||
config :logger, :info,
|
||||
path: "/path/to/info.log",
|
||||
level: :info
|
||||
|
||||
config :logger, :error,
|
||||
path: "/path/to/error.log",
|
||||
level: :error
|
||||
```
|
||||
|
||||
#### Filtering specific metadata terms
|
||||
|
||||
This example only logs `:info` statements originating from the `:ui` OTP app; the `:application` metadata key is auto-populated by `Logger`.
|
||||
|
||||
```elixir
|
||||
config :logger,
|
||||
backends: [{LoggerFileBackend, :ui}]
|
||||
|
||||
config :logger, :ui,
|
||||
path: "/path/to/ui.log",
|
||||
level: :info,
|
||||
metadata_filter: [application: :ui]
|
||||
```
|
||||
|
||||
This example only writes log statements with a custom metadata key to the file.
|
||||
|
||||
```elixir
|
||||
# in a config file:
|
||||
config :logger,
|
||||
backends: [{LoggerFileBackend, :device_1}]
|
||||
|
||||
config :logger, :device_1,
|
||||
path: "/path/to/device_1.log",
|
||||
level: :debug,
|
||||
metadata_filter: [device: 1]
|
||||
|
||||
# Usage:
|
||||
# anywhere in the code:
|
||||
Logger.info("statement", device: 1)
|
||||
|
||||
# or, for a single process, e.g., a GenServer:
|
||||
# in init/1:
|
||||
Logger.metadata(device: 1)
|
||||
# ^ sets device: 1 for all subsequent log statements from this process.
|
||||
|
||||
# Later, in other code (handle_cast/2, etc.)
|
||||
Logger.info("statement") # <= already tagged with the device_1 metadata
|
||||
```
|
||||
|
||||
## Additional Phoenix Configurations
|
||||
|
||||
Phoenix makes use of its own `mix.exs` file to track dependencies and additional applications. Add the following to your `mix.exs`:
|
||||
|
||||
```elixir
|
||||
def application do
|
||||
[applications: [
|
||||
...,
|
||||
:logger_file_backend,
|
||||
...
|
||||
]
|
||||
]
|
||||
end
|
||||
|
||||
defp deps do
|
||||
[ ...
|
||||
{:logger_file_backend, "~> 0.0.10"},
|
||||
]
|
||||
end
|
||||
```
|
||||
|
||||
## Copyright and License
|
||||
|
||||
Copyright (c) 2014 Kurt Williams
|
||||
|
||||
This library licensed under the [MIT license](./LICENSE.md).
|
||||
|
||||
## Image Attribution
|
||||
|
||||
"log" by Matthew Weatherall from [the Noun Project](https://thenounproject.com/).
|
||||
BIN
deps/logger_file_backend/assets/logo.png
vendored
Normal file
BIN
deps/logger_file_backend/assets/logo.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
15
deps/logger_file_backend/hex_metadata.config
vendored
Normal file
15
deps/logger_file_backend/hex_metadata.config
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
{<<"links">>,
|
||||
[{<<"Changelog">>,
|
||||
<<"https://hexdocs.pm/logger_file_backend/changelog.html">>},
|
||||
{<<"GitHub">>,<<"https://github.com/onkel-dirtus/logger_file_backend">>}]}.
|
||||
{<<"name">>,<<"logger_file_backend">>}.
|
||||
{<<"version">>,<<"0.0.14">>}.
|
||||
{<<"description">>,<<"Simple logger backend that writes to a file">>}.
|
||||
{<<"elixir">>,<<"~> 1.0">>}.
|
||||
{<<"app">>,<<"logger_file_backend">>}.
|
||||
{<<"licenses">>,[<<"MIT">>]}.
|
||||
{<<"files">>,
|
||||
[<<"lib">>,<<"lib/logger_file_backend.ex">>,<<"assets/logo.png">>,
|
||||
<<"mix.exs">>,<<"README.md">>,<<"CHANGELOG.md">>,<<"LICENSE.md">>]}.
|
||||
{<<"requirements">>,[]}.
|
||||
{<<"build_tools">>,[<<"mix">>]}.
|
||||
273
deps/logger_file_backend/lib/logger_file_backend.ex
vendored
Normal file
273
deps/logger_file_backend/lib/logger_file_backend.ex
vendored
Normal file
@ -0,0 +1,273 @@
|
||||
defmodule LoggerFileBackend do
|
||||
@moduledoc """
|
||||
`LoggerFileBackend` is a custom backend for the elixir `:logger` application.
|
||||
"""
|
||||
|
||||
@behaviour :gen_event
|
||||
|
||||
@type path :: String.t()
|
||||
@type file :: :file.io_device()
|
||||
@type inode :: integer
|
||||
@type format :: String.t()
|
||||
@type level :: Logger.level()
|
||||
@type metadata :: [atom]
|
||||
|
||||
require Record
|
||||
Record.defrecordp(:file_info, Record.extract(:file_info, from_lib: "kernel/include/file.hrl"))
|
||||
|
||||
@default_format "$time $metadata[$level] $message\n"
|
||||
|
||||
def init({__MODULE__, name}) do
|
||||
{:ok, configure(name, [])}
|
||||
end
|
||||
|
||||
def handle_call({:configure, opts}, %{name: name} = state) do
|
||||
{:ok, :ok, configure(name, opts, state)}
|
||||
end
|
||||
|
||||
def handle_call(:path, %{path: path} = state) do
|
||||
{:ok, {:ok, path}, state}
|
||||
end
|
||||
|
||||
def handle_event(
|
||||
{level, _gl, {Logger, msg, ts, md}},
|
||||
%{level: min_level, metadata_filter: metadata_filter, metadata_reject: metadata_reject} =
|
||||
state
|
||||
) do
|
||||
level = to_logger_level(level)
|
||||
min_level = to_logger_level(min_level)
|
||||
|
||||
if (is_nil(min_level) or Logger.compare_levels(level, min_level) != :lt) and
|
||||
metadata_matches?(md, metadata_filter) and
|
||||
(is_nil(metadata_reject) or !metadata_matches?(md, metadata_reject)) do
|
||||
log_event(level, msg, ts, md, state)
|
||||
else
|
||||
{:ok, state}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_event(:flush, state) do
|
||||
# We're not buffering anything so this is a no-op
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
def handle_info({:EXIT, _pid, _reason}, %{io_device: io_device} = state)
|
||||
when not is_nil(io_device) do
|
||||
case File.close(io_device) do
|
||||
:ok -> {:ok, state}
|
||||
{:error, reason} -> raise "failure while closing file for reason: #{reason}"
|
||||
end
|
||||
end
|
||||
|
||||
def handle_info(_, state) do
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
# helpers
|
||||
|
||||
defp log_event(_level, _msg, _ts, _md, %{path: nil} = state) do
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
defp log_event(level, msg, ts, md, %{path: path, io_device: nil} = state)
|
||||
when is_binary(path) do
|
||||
case open_log(path) do
|
||||
{:ok, io_device, inode} ->
|
||||
log_event(level, msg, ts, md, %{state | io_device: io_device, inode: inode})
|
||||
|
||||
_other ->
|
||||
{:ok, state}
|
||||
end
|
||||
end
|
||||
|
||||
defp log_event(
|
||||
level,
|
||||
msg,
|
||||
ts,
|
||||
md,
|
||||
%{path: path, io_device: io_device, inode: inode, rotate: rotate} = state
|
||||
)
|
||||
when is_binary(path) do
|
||||
if !is_nil(inode) and inode == get_inode(path) and rotate(path, rotate) do
|
||||
output = format_event(level, msg, ts, md, state)
|
||||
|
||||
try do
|
||||
IO.write(io_device, output)
|
||||
{:ok, state}
|
||||
rescue
|
||||
ErlangError ->
|
||||
case open_log(path) do
|
||||
{:ok, io_device, inode} ->
|
||||
IO.write(io_device, prune(output))
|
||||
{:ok, %{state | io_device: io_device, inode: inode}}
|
||||
|
||||
_other ->
|
||||
{:ok, %{state | io_device: nil, inode: nil}}
|
||||
end
|
||||
end
|
||||
else
|
||||
File.close(io_device)
|
||||
log_event(level, msg, ts, md, %{state | io_device: nil, inode: nil})
|
||||
end
|
||||
end
|
||||
|
||||
defp rename_file(path, keep) do
|
||||
File.rm("#{path}.#{keep}")
|
||||
|
||||
Enum.each((keep - 1)..1, fn x -> File.rename("#{path}.#{x}", "#{path}.#{x + 1}") end)
|
||||
|
||||
case File.rename(path, "#{path}.1") do
|
||||
:ok -> false
|
||||
_ -> true
|
||||
end
|
||||
end
|
||||
|
||||
defp rotate(path, %{max_bytes: max_bytes, keep: keep})
|
||||
when is_integer(max_bytes) and is_integer(keep) and keep > 0 do
|
||||
case :file.read_file_info(path, [:raw]) do
|
||||
{:ok, file_info(size: size)} ->
|
||||
if size >= max_bytes, do: rename_file(path, keep), else: true
|
||||
|
||||
_ ->
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
defp rotate(_path, nil), do: true
|
||||
|
||||
defp open_log(path) do
|
||||
case path |> Path.dirname() |> File.mkdir_p() do
|
||||
:ok ->
|
||||
case File.open(path, [:append, :utf8]) do
|
||||
{:ok, io_device} -> {:ok, io_device, get_inode(path)}
|
||||
other -> other
|
||||
end
|
||||
|
||||
other ->
|
||||
other
|
||||
end
|
||||
end
|
||||
|
||||
defp format_event(level, msg, ts, md, %{format: format, metadata: keys}) do
|
||||
Logger.Formatter.format(format, level, msg, ts, take_metadata(md, keys))
|
||||
end
|
||||
|
||||
@doc false
|
||||
@spec metadata_matches?(Keyword.t(), nil | Keyword.t()) :: true | false
|
||||
def metadata_matches?(_md, nil), do: true
|
||||
# all of the filter keys are present
|
||||
def metadata_matches?(_md, []), do: true
|
||||
|
||||
def metadata_matches?(md, [{key, [_ | _] = val} | rest]) do
|
||||
case Keyword.fetch(md, key) do
|
||||
{:ok, md_val} ->
|
||||
md_val in val && metadata_matches?(md, rest)
|
||||
|
||||
# fail on first mismatch
|
||||
_ ->
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def metadata_matches?(md, [{key, val} | rest]) do
|
||||
case Keyword.fetch(md, key) do
|
||||
{:ok, ^val} ->
|
||||
metadata_matches?(md, rest)
|
||||
|
||||
# fail on first mismatch
|
||||
_ ->
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
defp take_metadata(metadata, :all), do: metadata
|
||||
|
||||
defp take_metadata(metadata, keys) do
|
||||
metadatas =
|
||||
Enum.reduce(keys, [], fn key, acc ->
|
||||
case Keyword.fetch(metadata, key) do
|
||||
{:ok, val} -> [{key, val} | acc]
|
||||
:error -> acc
|
||||
end
|
||||
end)
|
||||
|
||||
Enum.reverse(metadatas)
|
||||
end
|
||||
|
||||
defp get_inode(path) do
|
||||
case :file.read_file_info(path, [:raw]) do
|
||||
{:ok, file_info(inode: inode)} -> inode
|
||||
{:error, _} -> nil
|
||||
end
|
||||
end
|
||||
|
||||
defp configure(name, opts) do
|
||||
state = %{
|
||||
name: nil,
|
||||
path: nil,
|
||||
io_device: nil,
|
||||
inode: nil,
|
||||
format: nil,
|
||||
level: nil,
|
||||
metadata: nil,
|
||||
metadata_filter: nil,
|
||||
metadata_reject: nil,
|
||||
rotate: nil
|
||||
}
|
||||
|
||||
configure(name, opts, state)
|
||||
end
|
||||
|
||||
defp configure(name, opts, state) do
|
||||
env = Application.get_env(:logger, name, [])
|
||||
opts = Keyword.merge(env, opts)
|
||||
Application.put_env(:logger, name, opts)
|
||||
|
||||
level = Keyword.get(opts, :level)
|
||||
metadata = Keyword.get(opts, :metadata, [])
|
||||
format_opts = Keyword.get(opts, :format, @default_format)
|
||||
format = Logger.Formatter.compile(format_opts)
|
||||
path = Keyword.get(opts, :path)
|
||||
metadata_filter = Keyword.get(opts, :metadata_filter)
|
||||
metadata_reject = Keyword.get(opts, :metadata_reject)
|
||||
rotate = Keyword.get(opts, :rotate)
|
||||
|
||||
%{
|
||||
state
|
||||
| name: name,
|
||||
path: path,
|
||||
format: format,
|
||||
level: level,
|
||||
metadata: metadata,
|
||||
metadata_filter: metadata_filter,
|
||||
metadata_reject: metadata_reject,
|
||||
rotate: rotate
|
||||
}
|
||||
end
|
||||
|
||||
@replacement "<EFBFBD>"
|
||||
|
||||
@spec prune(IO.chardata()) :: IO.chardata()
|
||||
def prune(binary) when is_binary(binary), do: prune_binary(binary, "")
|
||||
def prune([h | t]) when h in 0..1_114_111, do: [h | prune(t)]
|
||||
def prune([h | t]), do: [prune(h) | prune(t)]
|
||||
def prune([]), do: []
|
||||
def prune(_), do: @replacement
|
||||
|
||||
defp prune_binary(<<h::utf8, t::binary>>, acc),
|
||||
do: prune_binary(t, <<acc::binary, h::utf8>>)
|
||||
|
||||
defp prune_binary(<<_, t::binary>>, acc),
|
||||
do: prune_binary(t, <<acc::binary, @replacement>>)
|
||||
|
||||
defp prune_binary(<<>>, acc),
|
||||
do: acc
|
||||
|
||||
defp to_logger_level(:warn) do
|
||||
if Version.compare(System.version(), "1.11.0") != :lt,
|
||||
do: :warning,
|
||||
else: :warn
|
||||
end
|
||||
|
||||
defp to_logger_level(level), do: level
|
||||
end
|
||||
63
deps/logger_file_backend/mix.exs
vendored
Normal file
63
deps/logger_file_backend/mix.exs
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
defmodule LoggerFileBackend.Mixfile do
|
||||
use Mix.Project
|
||||
|
||||
@source_url "https://github.com/onkel-dirtus/logger_file_backend"
|
||||
@version "0.0.14"
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :logger_file_backend,
|
||||
version: @version,
|
||||
elixir: "~> 1.0",
|
||||
package: package(),
|
||||
deps: deps(),
|
||||
docs: docs()
|
||||
]
|
||||
end
|
||||
|
||||
def application do
|
||||
[extra_applications: [:logger]]
|
||||
end
|
||||
|
||||
defp package do
|
||||
[
|
||||
description: "Simple logger backend that writes to a file",
|
||||
maintainers: ["Kurt Williams", "Everett Griffiths"],
|
||||
licenses: ["MIT"],
|
||||
files: [
|
||||
"lib",
|
||||
"assets/logo.png",
|
||||
"mix.exs",
|
||||
"README*",
|
||||
"CHANGELOG*",
|
||||
"LICENSE*"
|
||||
],
|
||||
links: %{
|
||||
"Changelog" => "https://hexdocs.pm/logger_file_backend/changelog.html",
|
||||
"GitHub" => @source_url
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
defp deps do
|
||||
[
|
||||
{:credo, "~> 1.7.5", only: [:dev, :test]},
|
||||
{:ex_doc, ">= 0.32.1", only: :dev, runtime: false}
|
||||
]
|
||||
end
|
||||
|
||||
defp docs do
|
||||
[
|
||||
extras: [
|
||||
"CHANGELOG.md": [],
|
||||
"LICENSE.md": [title: "License"],
|
||||
"README.md": [title: "Overview"]
|
||||
],
|
||||
main: "readme",
|
||||
source_url: @source_url,
|
||||
source_ref: "v#{@version}",
|
||||
logo: "assets/logo.png",
|
||||
formatters: ["html"]
|
||||
]
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user