feat: Move main router and menu into app to allow easier development
|
@ -7,7 +7,6 @@ defmodule Admin.Router do
|
|||
plug :fetch_flash
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
plug :put_layout, {CoreWeb.LayoutView, :app}
|
||||
end
|
||||
|
||||
pipeline :require_admin do
|
||||
|
@ -18,5 +17,5 @@ defmodule Admin.Router do
|
|||
plug :accepts, ["json"]
|
||||
end
|
||||
|
||||
use Kaffy.Routes, scope: "/", pipe_through: [:require_admin]
|
||||
use Admin.Routes
|
||||
end
|
||||
|
|
7
apps/admin/lib/admin/routes.ex
Normal file
|
@ -0,0 +1,7 @@
|
|||
defmodule Admin.Routes do
|
||||
defmacro __using__(_opts \\ []) do
|
||||
quote do
|
||||
use Kaffy.Routes, scope: "/admin", pipe_through: [:require_admin]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -9,6 +9,10 @@
|
|||
@import "blog";
|
||||
@import "code";
|
||||
|
||||
body {
|
||||
outline: 1px pink solid;
|
||||
}
|
||||
|
||||
input[type="checkbox"]::after {
|
||||
content: "";
|
||||
color: currentColor;
|
|
@ -1,31 +0,0 @@
|
|||
/* This file is for your main application css. */
|
||||
@import "./phoenix.css";
|
||||
|
||||
/* Alerts and form errors */
|
||||
.alert {
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.alert-info {
|
||||
color: #31708f;
|
||||
background-color: #d9edf7;
|
||||
border-color: #bce8f1;
|
||||
}
|
||||
.alert-warning {
|
||||
color: #8a6d3b;
|
||||
background-color: #fcf8e3;
|
||||
border-color: #faebcc;
|
||||
}
|
||||
.alert-danger {
|
||||
color: #a94442;
|
||||
background-color: #f2dede;
|
||||
border-color: #ebccd1;
|
||||
}
|
||||
.alert p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.alert:empty {
|
||||
display: none;
|
||||
}
|
|
@ -13,3 +13,45 @@ import "../css/app.css"
|
|||
// import socket from "./socket"
|
||||
//
|
||||
import "phoenix_html"
|
||||
import { ready } from "./utils"
|
||||
|
||||
function togglePasswordFieldVisibility()
|
||||
{
|
||||
const passwordFields = document.querySelectorAll('[name="user[password]"]')
|
||||
passwordFields.forEach((el) => {
|
||||
if (el.type == 'password')
|
||||
{
|
||||
el.type = 'text'
|
||||
}
|
||||
else
|
||||
{
|
||||
el.type = 'password'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const toggleSidebar = (event) => {
|
||||
document.querySelectorAll('.sidebar').forEach((el) => {
|
||||
el.classList.toggle('visible')
|
||||
})
|
||||
}
|
||||
|
||||
ready(() => {
|
||||
document.getElementById('nav-toggle').onclick = function(){
|
||||
document.getElementById("nav-content").classList.toggle("hidden");
|
||||
}
|
||||
|
||||
document.querySelectorAll('.js-passwordRevealer').forEach((el) => {
|
||||
el.addEventListener('click', togglePasswordFieldVisibility)
|
||||
})
|
||||
|
||||
document.querySelectorAll('.js-SidebarOpener').forEach((el) => {
|
||||
el.addEventListener('click', toggleSidebar)
|
||||
})
|
||||
|
||||
document.querySelectorAll('.js-flash-closer').forEach((el) => {
|
||||
el.addEventListener('click', () => {
|
||||
el.closest('.js-flash').remove()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
5943
apps/app/assets/package-lock.json
generated
|
@ -4,11 +4,22 @@
|
|||
"license": "MIT",
|
||||
"scripts": {
|
||||
"deploy": "webpack --mode production",
|
||||
"watch": "webpack --mode development --watch"
|
||||
"watch": "webpack --mode development --watch",
|
||||
"preinstall": "npx npm-force-resolutions",
|
||||
"profile": "webpack --mode development --plugin webpack/lib/debug/ProfilingPlugin"
|
||||
},
|
||||
"dependencies": {
|
||||
"phoenix": "file:../../../deps/phoenix",
|
||||
"phoenix_html": "file:../../../deps/phoenix_html"
|
||||
"@fortawesome/fontawesome-free": "^5.14.0",
|
||||
"autoprefixer": "^9.8.6",
|
||||
"csswring": "^7.0.0",
|
||||
"glob": "^7.1.6",
|
||||
"gulp": "^4.0.2",
|
||||
"phoenix": "file:/../../../deps/phoenix",
|
||||
"phoenix_html": "file:/../../../deps/phoenix_html",
|
||||
"postcss-color-function": "^4.1.0",
|
||||
"simplemde": "^1.11.2",
|
||||
"stylelint": "^13.6.1",
|
||||
"tailwindcss": "^1.7.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.0.0",
|
||||
|
@ -16,12 +27,26 @@
|
|||
"babel-loader": "^8.0.0",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
"css-loader": "^3.4.2",
|
||||
"sass-loader": "^8.0.2",
|
||||
"node-sass": "^4.13.1",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"file-loader": "^6.0.0",
|
||||
"image-webpack-loader": "^6.0.0",
|
||||
"less": "^3.11.3",
|
||||
"less-loader": "^6.2.0",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"node-sass": "^4.13.1",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.1",
|
||||
"postcss-css-variables": "^0.17.0",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"sass-loader": "^8.0.2",
|
||||
"style-loader": "^1.2.1",
|
||||
"stylelint-config-standard": "^20.0.0",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"terser-webpack-plugin": "^2.3.2",
|
||||
"webpack": "4.41.5",
|
||||
"webpack-cli": "^3.3.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"graceful-fs": "4.2.3"
|
||||
}
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
|
@ -5,6 +5,8 @@ const TerserPlugin = require('terser-webpack-plugin');
|
|||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
|
||||
const nodeModulesPath = path.resolve(__dirname, 'node_modules')
|
||||
|
||||
module.exports = (env, options) => {
|
||||
const devMode = options.mode !== 'production';
|
||||
|
||||
|
@ -15,17 +17,42 @@ module.exports = (env, options) => {
|
|||
new OptimizeCSSAssetsPlugin({})
|
||||
]
|
||||
},
|
||||
mode: options.mode,
|
||||
devtool: devMode ? 'source-map' : undefined,
|
||||
entry: {
|
||||
'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js'])
|
||||
'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js']),
|
||||
'content-editor': ['./js/content-editor.js'],
|
||||
'tailwind': ['./tailwind.config.js'],
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
path: path.resolve(__dirname, '../priv/static/js'),
|
||||
publicPath: '/js/'
|
||||
filename: 'js/[name].js',
|
||||
path: path.resolve(__dirname, '../priv/static/')
|
||||
},
|
||||
devtool: devMode ? 'source-map' : undefined,
|
||||
module: {
|
||||
rules: [
|
||||
// For images and fonts found in our scss files
|
||||
{
|
||||
test: /\.(jpg|jpeg|gif|png)$/,
|
||||
use: [
|
||||
'file-loader',
|
||||
{
|
||||
loader: 'image-webpack-loader',
|
||||
options: {
|
||||
disable: devMode,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(woff2?|ttf|eot|svg)(\?[a-z0-9\=\.]+)?$/,
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
publicPath: '/fonts',
|
||||
outputPath: (url, resourcePath, context) => {
|
||||
return `/fonts/${url}`;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
|
@ -34,18 +61,45 @@ module.exports = (env, options) => {
|
|||
}
|
||||
},
|
||||
{
|
||||
test: /\.[s]?css$/,
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
'css-loader',
|
||||
'sass-loader',
|
||||
{loader: MiniCssExtractPlugin.loader, options: {sourceMap: true}},
|
||||
{loader: 'css-loader', options: {sourceMap: true}},
|
||||
{loader: 'postcss-loader', options: {sourceMap: true}},
|
||||
],
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new MiniCssExtractPlugin({ filename: '../css/app.css' }),
|
||||
new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
|
||||
]
|
||||
new MiniCssExtractPlugin({
|
||||
filename: 'css/[name].css',
|
||||
chunkFilename: '[id].css',
|
||||
}),
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: path.resolve(__dirname, 'static'),
|
||||
to: path.resolve(__dirname, '../priv/static'),
|
||||
},
|
||||
]),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
"../webfonts/fa-brands-400.eot": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot"),
|
||||
"../webfonts/fa-brands-400.woff2": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2"),
|
||||
"../webfonts/fa-brands-400.woff": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff"),
|
||||
"../webfonts/fa-brands-400.ttf": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf"),
|
||||
"../webfonts/fa-brands-400.svg": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.svg"),
|
||||
"../webfonts/fa-regular-400.eot": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot"),
|
||||
"../webfonts/fa-regular-400.woff2": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2"),
|
||||
"../webfonts/fa-regular-400.woff": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff"),
|
||||
"../webfonts/fa-regular-400.ttf": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.ttf"),
|
||||
"../webfonts/fa-regular-400.svg": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.svg"),
|
||||
"../webfonts/fa-solid-900.eot": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot"),
|
||||
"../webfonts/fa-solid-900.woff2": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2"),
|
||||
"../webfonts/fa-solid-900.woff": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff"),
|
||||
"../webfonts/fa-solid-900.ttf": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.ttf"),
|
||||
"../webfonts/fa-solid-900.svg": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.svg"),
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
|
@ -10,6 +10,8 @@ defmodule App.Application do
|
|||
App.Repo,
|
||||
# Start the Telemetry supervisor
|
||||
AppWeb.Telemetry,
|
||||
# Set up the pubsub server
|
||||
{Phoenix.PubSub, name: App.PubSub},
|
||||
# Start the Endpoint (http/https)
|
||||
AppWeb.Endpoint
|
||||
# Start a worker by calling: AppWeb.Worker.start_link(arg)
|
||||
|
|
|
@ -26,6 +26,12 @@ defmodule AppWeb.Endpoint do
|
|||
gzip: false,
|
||||
only: ~w(css fonts images js favicon.ico robots.txt)
|
||||
|
||||
plug Plug.Static,
|
||||
at: "/kaffy",
|
||||
from: :kaffy,
|
||||
gzip: false,
|
||||
only: ~w(assets)
|
||||
|
||||
# Code reloading can be explicitly enabled under the
|
||||
# :code_reloader configuration of your endpoint.
|
||||
if code_reloading? do
|
||||
|
@ -50,5 +56,7 @@ defmodule AppWeb.Endpoint do
|
|||
plug Plug.MethodOverride
|
||||
plug Plug.Head
|
||||
plug Plug.Session, @session_options
|
||||
plug Pow.Plug.Session, otp_app: :auth_web
|
||||
plug PowPersistentSession.Plug.Cookie
|
||||
plug AppWeb.Router
|
||||
end
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
defmodule AppWeb.Router do
|
||||
use AppWeb, :router
|
||||
use Pow.Phoenix.Router
|
||||
use Pow.Extension.Phoenix.Router,
|
||||
extensions: [PowResetPassword, PowEmailConfirmation]
|
||||
|
||||
alias AuthWeb.Plugs.{RequireAdmin}
|
||||
|
||||
pipeline :browser do
|
||||
plug :accepts, ["html"]
|
||||
|
@ -7,13 +12,21 @@ defmodule AppWeb.Router do
|
|||
plug :fetch_flash
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
plug :put_layout, {CoreWeb.LayoutView, :app}
|
||||
plug :put_layout, {AppWeb.LayoutView, :app}
|
||||
end
|
||||
|
||||
pipeline :api do
|
||||
plug :accepts, ["json"]
|
||||
end
|
||||
|
||||
pipeline :require_admin do
|
||||
plug(RequireAdmin)
|
||||
end
|
||||
|
||||
pipeline :require_auth do
|
||||
plug Pow.Plug.RequireAuthenticated, error_handler: Pow.Phoenix.PlugErrorHandler
|
||||
end
|
||||
|
||||
# Other scopes may use custom stacks.
|
||||
# scope "/api", AppWeb do
|
||||
# pipe_through :api
|
||||
|
@ -33,5 +46,17 @@ defmodule AppWeb.Router do
|
|||
pipe_through :browser
|
||||
live_dashboard "/dashboard", metrics: AppWeb.Telemetry
|
||||
end
|
||||
|
||||
forward "/sent_emails", Bamboo.SentEmailViewerPlug
|
||||
end
|
||||
|
||||
scope "/" do
|
||||
pipe_through :browser
|
||||
|
||||
pow_routes()
|
||||
pow_extension_routes()
|
||||
end
|
||||
|
||||
use Admin.Routes
|
||||
use Content.Routes
|
||||
end
|
||||
|
|
|
@ -20,16 +20,16 @@
|
|||
<% end %>
|
||||
<%= if Pow.Plug.current_user(@conn) do %>
|
||||
<li class="mr-3">
|
||||
<%= link "Sign Out", to: AuthWeb.Router.Helpers.pow_session_path(%URI{path: "/auth"}, :delete), method: :delete, class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" %>
|
||||
<%= link "Sign Out", to: Routes.pow_session_path(@conn, :delete), method: :delete, class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" %>
|
||||
</li>
|
||||
<% else %>
|
||||
<li class="mr-3">
|
||||
<%= link to: AuthWeb.Router.Helpers.pow_session_path(%URI{path: "/auth"}, :new), class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" do %>
|
||||
<%= link to: Routes.pow_session_path(@conn, :new), class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" do %>
|
||||
Log In
|
||||
<% end %>
|
||||
</li>
|
||||
<li class="mr-3">
|
||||
<%= link to: AuthWeb.Router.Helpers.pow_registration_path(%URI{path: "/auth"}, :new), class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" do %>
|
||||
<%= link to: Routes.pow_registration_path(@conn, :new), class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" do %>
|
||||
Sign Up
|
||||
<% end %>
|
||||
</li>
|
|
@ -1,3 +1,39 @@
|
|||
defmodule AppWeb.LayoutView do
|
||||
use AppWeb, :view
|
||||
|
||||
def title(view_module, template, assigns) do
|
||||
delegate_with_default(view_module, :title, [view_module, template, assigns], I18n.t!("en", "site.title"))
|
||||
end
|
||||
|
||||
def excerpt(view_module, template, assigns) do
|
||||
delegate_with_default(view_module, :excerpt, [view_module, template, assigns], I18n.t!("en", "site.excerpt"))
|
||||
end
|
||||
|
||||
def feed_tag(conn, view_module, view_template, assigns) do
|
||||
delegate_with_default(view_module, :feed_tag, [conn, view_module, view_template, assigns], nil)
|
||||
end
|
||||
|
||||
defp delegate_with_default(nil, _, _, default), do: default
|
||||
defp delegate_with_default(view_module, function_name, args, default) do
|
||||
sibling_layout = sibling_layout_view(view_module)
|
||||
if function_exported?(sibling_layout, function_name, args |> Enum.count()) do
|
||||
apply(sibling_layout, function_name, args)
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
defp sibling_layout_view(view_module) do
|
||||
view_module
|
||||
|> parent_module()
|
||||
|> Module.concat("LayoutView")
|
||||
end
|
||||
|
||||
defp parent_module(mod) do
|
||||
[_|tail] = Module.split(mod) |> Enum.reverse()
|
||||
|
||||
tail
|
||||
|> Enum.reverse()
|
||||
|> Module.concat()
|
||||
end
|
||||
end
|
||||
|
|
|
@ -39,6 +39,8 @@ defmodule App.MixProject do
|
|||
# Type `mix help deps` for examples and options.
|
||||
defp deps do
|
||||
[
|
||||
{:admin, in_umbrella: true},
|
||||
{:content, in_umbrella: true},
|
||||
{:core, in_umbrella: true},
|
||||
{:ecto_sql, "~> 3.4"},
|
||||
{:excoveralls, "~> 0.10", only: [:dev, :test]},
|
||||
|
|
|
@ -1,8 +1,31 @@
|
|||
defmodule App.LayoutViewTest do
|
||||
use App.ConnCase, async: true
|
||||
|
||||
# When testing helpers, you may want to import Phoenix.HTML and
|
||||
# use functions such as safe_to_string() to convert the helper
|
||||
# result into an HTML string.
|
||||
# import Phoenix.HTML
|
||||
import AppWeb.LayoutView
|
||||
|
||||
describe "title/3" do
|
||||
def default_title do
|
||||
I18n.t! "en", "site.title"
|
||||
end
|
||||
|
||||
test "for nil" do
|
||||
assert title(nil, nil, nil) =~ default_title()
|
||||
end
|
||||
end
|
||||
|
||||
describe "excerpt/3" do
|
||||
def default_excerpt do
|
||||
I18n.t! "en", "site.excerpt"
|
||||
end
|
||||
|
||||
test "for nil" do
|
||||
assert excerpt(nil, nil, nil) =~ default_excerpt()
|
||||
end
|
||||
end
|
||||
|
||||
describe "feed_tag/4" do
|
||||
test "for nil" do
|
||||
assert feed_tag(nil, nil, nil, nil) == nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,7 +10,6 @@ defmodule AuthWeb.Router do
|
|||
plug :fetch_flash
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
plug :put_layout, {CoreWeb.LayoutView, :app}
|
||||
end
|
||||
|
||||
pipeline :api do
|
||||
|
|
|
@ -5,5 +5,4 @@ defmodule AuthWeb.EmailView do
|
|||
pattern: "**/*"
|
||||
|
||||
import Phoenix.HTML, only: [raw: 1]
|
||||
import CoreWeb.EmailHelpers
|
||||
end
|
||||
|
|
|
@ -29,7 +29,7 @@ defmodule Content.MarkupField do
|
|||
"""
|
||||
end
|
||||
|
||||
def render_index(conn, resource, field, _opts) do
|
||||
def render_index(_conn, resource, field, _opts) do
|
||||
case Map.get(resource, field) do
|
||||
nil ->
|
||||
""
|
||||
|
|
|
@ -77,8 +77,14 @@ defmodule Content.PostsController do
|
|||
e in Phoenix.Template.UndefinedError ->
|
||||
case e do
|
||||
%{template: ^path} ->
|
||||
router =
|
||||
case conn do
|
||||
%{private: %{phoenix_router: router}} -> router
|
||||
_ -> Content.Router
|
||||
end
|
||||
|
||||
# The static page we're looking for is missing, so this is just a 404
|
||||
raise Phoenix.Router.NoRouteError.exception(conn: conn, router: Content.Router)
|
||||
raise Phoenix.Router.NoRouteError.exception(conn: conn, router: router)
|
||||
_ ->
|
||||
# We aren't missing the static page, we're missing a partial. This is probably
|
||||
# a developer error, so bubble it up
|
||||
|
|
|
@ -8,57 +8,19 @@ defmodule Content.Router do
|
|||
plug :fetch_flash
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
plug :put_layout, {CoreWeb.LayoutView, :app}
|
||||
end
|
||||
|
||||
pipeline :api do
|
||||
plug :accepts, ["json"]
|
||||
end
|
||||
|
||||
pipeline :feed do
|
||||
plug :accepts, ["rss"]
|
||||
plug :fetch_session
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
pipeline :require_admin do
|
||||
plug(RequireAdmin)
|
||||
end
|
||||
|
||||
pipeline :require_auth do
|
||||
plug Pow.Plug.RequireAuthenticated, error_handler: Pow.Phoenix.PlugErrorHandler
|
||||
end
|
||||
|
||||
pipeline :require_admin do
|
||||
plug(RequireAdmin)
|
||||
end
|
||||
|
||||
pipeline :admin_layout do
|
||||
plug :put_layout, {Content.LayoutView, :admin}
|
||||
end
|
||||
|
||||
scope "/", Content do
|
||||
pipe_through([:browser, :require_auth, :require_admin, :admin_layout])
|
||||
|
||||
put "/posts/preview", PostsController, :preview
|
||||
post "/posts/preview", PostsController, :preview
|
||||
end
|
||||
|
||||
scope "/", Content do
|
||||
pipe_through :feed # Use the default browser stack
|
||||
|
||||
get "/category/:category/feed.rss", FeedsController, :index, as: :category_feed
|
||||
get "/feed.rss", FeedsController, :index, as: :index_feed
|
||||
end
|
||||
|
||||
scope "/", Content do
|
||||
pipe_through :browser # Use the default browser stack
|
||||
|
||||
resources "/comments", CommentController, as: :comment, only: [:create, :delete, :update]
|
||||
get "/page/:page", PostsController, :index_posts, as: :blog_page
|
||||
get "/category/:category", PostsController, :index_posts, as: :category
|
||||
get "/category/:category/page/:page", PostsController, :index, as: :category_page
|
||||
post "/wp-login.php", PostPasswordController, :create
|
||||
get "/", PostsController, :index
|
||||
resources "/sitemap", SitemapController, only: [:index]
|
||||
get "/:id", PostsController, :show
|
||||
get "/:id/:page", PostsController, :show, as: :paged_post
|
||||
end
|
||||
use Content.Routes
|
||||
end
|
||||
|
|
40
apps/content/lib/content_web/routes.ex
Normal file
|
@ -0,0 +1,40 @@
|
|||
defmodule Content.Routes do
|
||||
defmacro __using__(_opts \\ []) do
|
||||
quote do
|
||||
pipeline :feed do
|
||||
plug :accepts, ["rss"]
|
||||
plug :fetch_session
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
end
|
||||
|
||||
scope "/", Content do
|
||||
pipe_through([:browser, :require_auth, :require_admin])
|
||||
|
||||
put "/posts/preview", PostsController, :preview
|
||||
post "/posts/preview", PostsController, :preview
|
||||
end
|
||||
|
||||
scope "/", Content do
|
||||
pipe_through :feed # Use the default browser stack
|
||||
|
||||
get "/category/:category/feed.rss", FeedsController, :index, as: :category_feed
|
||||
get "/feed.rss", FeedsController, :index, as: :index_feed
|
||||
end
|
||||
|
||||
scope "/", Content do
|
||||
pipe_through :browser # Use the default browser stack
|
||||
|
||||
resources "/comments", CommentController, as: :comment, only: [:create, :delete, :update]
|
||||
get "/page/:page", PostsController, :index_posts, as: :blog_page
|
||||
get "/category/:category", PostsController, :index_posts, as: :category
|
||||
get "/category/:category/page/:page", PostsController, :index, as: :category_page
|
||||
post "/wp-login.php", PostPasswordController, :create
|
||||
get "/", PostsController, :index
|
||||
resources "/sitemap", SitemapController, only: [:index]
|
||||
get "/:id", PostsController, :show
|
||||
get "/:id/:page", PostsController, :show, as: :paged_post
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
22
apps/content/lib/content_web/templates/layout/app.html.eex
Normal file
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title><%= title(@view_module, @view_template, assigns) %></title>
|
||||
<link rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
||||
<%= feed_tag(@conn, @view_module, @view_template, assigns) %>
|
||||
<script defer type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||
</head>
|
||||
<body class="text-gray-800 antialiased">
|
||||
<main role="main">
|
||||
<!-- Page Contents -->
|
||||
<div class="bg-gray-100 min-h-screen">
|
||||
<%= flash_block(@conn) %>
|
||||
|
||||
<%= @inner_content %>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
|
@ -9,7 +9,7 @@
|
|||
<div class="Article-content <%= if post.format, do: post.format.slug %> e-content">
|
||||
<%= render "thumb.html", post: post, thumbs: @thumbs %>
|
||||
<div class="Article-content-words">
|
||||
<%= raw post |> Content.Post.content_page(1) |> Content.Post.before_more |> process_content |> () |> raw %>
|
||||
<%= raw post |> Content.Post.content_page(1) |> Content.Post.before_more |> process_content |> raw %>
|
||||
<%= if post.content =~ "<!--more-->" do %>
|
||||
<p>
|
||||
<%= link "Keep Reading", to: Routes.posts_path(@conn, :show, post) %>
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="w-full lg:w-8/12 px-4 ml-auto mr-auto text-center my-12">
|
||||
<%= styled_button_link "Log In", to: AuthWeb.Router.Helpers.pow_session_path(%URI{path: "/auth"}, :new) %>
|
||||
<%= styled_button_link "Sign Up", to: AuthWeb.Router.Helpers.pow_registration_path(%URI{path: "/auth"}, :new) %>
|
||||
<%= styled_button_link "Log In", to: "/session/new" %>
|
||||
<%= styled_button_link "Sign Up", to: "/registration/new" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -160,8 +160,8 @@
|
|||
</h1>
|
||||
</div>
|
||||
<div class="w-full lg:w-8/12 px-4 ml-auto mr-auto text-center my-12">
|
||||
<%= styled_button_link "Log In", to: AuthWeb.Router.Helpers.pow_session_path(%URI{path: "/auth"}, :new) %>
|
||||
<%= styled_button_link "Sign Up", to: AuthWeb.Router.Helpers.pow_registration_path(%URI{path: "/auth"}, :new) %>
|
||||
<%= styled_button_link "Log In", to: "/session/new" %>
|
||||
<%= styled_button_link "Sign Up", to: "/registration/new" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"presets": [
|
||||
"@babel/preset-env"
|
||||
]
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
// We need to import the CSS so that webpack will load it.
|
||||
// The MiniCssExtractPlugin is used to separate it out into
|
||||
// its own CSS file.
|
||||
import "../css/app.css"
|
||||
|
||||
// webpack automatically bundles all modules in your
|
||||
// entry points. Those entry points can be configured
|
||||
// in "webpack.config.js".
|
||||
//
|
||||
// Import deps with the dep name or local files with a relative path, for example:
|
||||
//
|
||||
// import {Socket} from "phoenix"
|
||||
// import socket from "./socket"
|
||||
//
|
||||
import "phoenix_html"
|
||||
import { ready } from "./utils"
|
||||
|
||||
function togglePasswordFieldVisibility()
|
||||
{
|
||||
const passwordFields = document.querySelectorAll('[name="user[password]"]')
|
||||
passwordFields.forEach((el) => {
|
||||
if (el.type == 'password')
|
||||
{
|
||||
el.type = 'text'
|
||||
}
|
||||
else
|
||||
{
|
||||
el.type = 'password'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const toggleSidebar = (event) => {
|
||||
document.querySelectorAll('.sidebar').forEach((el) => {
|
||||
el.classList.toggle('visible')
|
||||
})
|
||||
}
|
||||
|
||||
ready(() => {
|
||||
document.getElementById('nav-toggle').onclick = function(){
|
||||
document.getElementById("nav-content").classList.toggle("hidden");
|
||||
}
|
||||
|
||||
document.querySelectorAll('.js-passwordRevealer').forEach((el) => {
|
||||
el.addEventListener('click', togglePasswordFieldVisibility)
|
||||
})
|
||||
|
||||
document.querySelectorAll('.js-SidebarOpener').forEach((el) => {
|
||||
el.addEventListener('click', toggleSidebar)
|
||||
})
|
||||
|
||||
document.querySelectorAll('.js-flash-closer').forEach((el) => {
|
||||
el.addEventListener('click', () => {
|
||||
el.closest('.js-flash').remove()
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,63 +0,0 @@
|
|||
// NOTE: The contents of this file will only be executed if
|
||||
// you uncomment its entry in "assets/js/app.js".
|
||||
|
||||
// To use Phoenix channels, the first step is to import Socket,
|
||||
// and connect at the socket path in "lib/web/endpoint.ex".
|
||||
//
|
||||
// Pass the token on params as below. Or remove it
|
||||
// from the params if you are not using authentication.
|
||||
import {Socket} from "phoenix"
|
||||
|
||||
let socket = new Socket("/socket", {params: {token: window.userToken}})
|
||||
|
||||
// When you connect, you'll often need to authenticate the client.
|
||||
// For example, imagine you have an authentication plug, `MyAuth`,
|
||||
// which authenticates the session and assigns a `:current_user`.
|
||||
// If the current user exists you can assign the user's token in
|
||||
// the connection for use in the layout.
|
||||
//
|
||||
// In your "lib/web/router.ex":
|
||||
//
|
||||
// pipeline :browser do
|
||||
// ...
|
||||
// plug MyAuth
|
||||
// plug :put_user_token
|
||||
// end
|
||||
//
|
||||
// defp put_user_token(conn, _) do
|
||||
// if current_user = conn.assigns[:current_user] do
|
||||
// token = Phoenix.Token.sign(conn, "user socket", current_user.id)
|
||||
// assign(conn, :user_token, token)
|
||||
// else
|
||||
// conn
|
||||
// end
|
||||
// end
|
||||
//
|
||||
// Now you need to pass this token to JavaScript. You can do so
|
||||
// inside a script tag in "lib/web/templates/layout/app.html.eex":
|
||||
//
|
||||
// <script>window.userToken = "<%= assigns[:user_token] %>";</script>
|
||||
//
|
||||
// You will need to verify the user token in the "connect/3" function
|
||||
// in "lib/web/channels/user_socket.ex":
|
||||
//
|
||||
// def connect(%{"token" => token}, socket, _connect_info) do
|
||||
// # max_age: 1209600 is equivalent to two weeks in seconds
|
||||
// case Phoenix.Token.verify(socket, "user socket", token, max_age: 1209600) do
|
||||
// {:ok, user_id} ->
|
||||
// {:ok, assign(socket, :user, user_id)}
|
||||
// {:error, reason} ->
|
||||
// :error
|
||||
// end
|
||||
// end
|
||||
//
|
||||
// Finally, connect to the socket:
|
||||
socket.connect()
|
||||
|
||||
// Now that you are connected, you can join channels with a topic:
|
||||
let channel = socket.channel("topic:subtopic", {})
|
||||
channel.join()
|
||||
.receive("ok", resp => { console.log("Joined successfully", resp) })
|
||||
.receive("error", resp => { console.log("Unable to join", resp) })
|
||||
|
||||
export default socket
|
12798
apps/core/assets/package-lock.json
generated
|
@ -1,52 +0,0 @@
|
|||
{
|
||||
"repository": {},
|
||||
"description": " ",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"deploy": "webpack --mode production",
|
||||
"watch": "webpack --mode development --watch",
|
||||
"preinstall": "npx npm-force-resolutions",
|
||||
"profile": "webpack --mode development --plugin webpack/lib/debug/ProfilingPlugin"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.14.0",
|
||||
"autoprefixer": "^9.8.6",
|
||||
"csswring": "^7.0.0",
|
||||
"glob": "^7.1.6",
|
||||
"gulp": "^4.0.2",
|
||||
"phoenix": "file:../deps/phoenix",
|
||||
"phoenix_html": "file:../deps/phoenix_html",
|
||||
"postcss-color-function": "^4.1.0",
|
||||
"simplemde": "^1.11.2",
|
||||
"stylelint": "^13.6.1",
|
||||
"tailwindcss": "^1.7.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.0.0",
|
||||
"@babel/preset-env": "^7.0.0",
|
||||
"babel-loader": "^8.0.0",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
"css-loader": "^3.4.2",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"file-loader": "^6.0.0",
|
||||
"image-webpack-loader": "^6.0.0",
|
||||
"less": "^3.11.3",
|
||||
"less-loader": "^6.2.0",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"node-sass": "^4.13.1",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.1",
|
||||
"postcss-css-variables": "^0.17.0",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"sass-loader": "^8.0.2",
|
||||
"style-loader": "^1.2.1",
|
||||
"stylelint-config-standard": "^20.0.0",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"terser-webpack-plugin": "^2.3.2",
|
||||
"webpack": "4.41.5",
|
||||
"webpack-cli": "^3.3.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"graceful-fs": "4.2.3"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 14 KiB |
|
@ -1,5 +0,0 @@
|
|||
# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
|
||||
#
|
||||
# To ban all spiders from the entire site uncomment the next two lines:
|
||||
# User-agent: *
|
||||
# Disallow: /
|
|
@ -1,105 +0,0 @@
|
|||
const path = require('path');
|
||||
const glob = require('glob');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
|
||||
const nodeModulesPath = path.resolve(__dirname, 'node_modules')
|
||||
|
||||
module.exports = (env, options) => {
|
||||
const devMode = options.mode !== 'production';
|
||||
|
||||
return {
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new TerserPlugin({ cache: true, parallel: true, sourceMap: devMode }),
|
||||
new OptimizeCSSAssetsPlugin({})
|
||||
]
|
||||
},
|
||||
mode: options.mode,
|
||||
devtool: devMode ? 'source-map' : undefined,
|
||||
entry: {
|
||||
'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js']),
|
||||
'content-editor': ['./js/content-editor.js'],
|
||||
'tailwind': ['./tailwind.config.js'],
|
||||
},
|
||||
output: {
|
||||
filename: 'js/[name].js',
|
||||
path: path.resolve(__dirname, '../priv/static/')
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
// For images and fonts found in our scss files
|
||||
{
|
||||
test: /\.(jpg|jpeg|gif|png)$/,
|
||||
use: [
|
||||
'file-loader',
|
||||
{
|
||||
loader: 'image-webpack-loader',
|
||||
options: {
|
||||
disable: devMode,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(woff2?|ttf|eot|svg)(\?[a-z0-9\=\.]+)?$/,
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
publicPath: '/fonts',
|
||||
outputPath: (url, resourcePath, context) => {
|
||||
return `/fonts/${url}`;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader'
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
{loader: MiniCssExtractPlugin.loader, options: {sourceMap: true}},
|
||||
{loader: 'css-loader', options: {sourceMap: true}},
|
||||
{loader: 'postcss-loader', options: {sourceMap: true}},
|
||||
],
|
||||
},
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new MiniCssExtractPlugin({
|
||||
filename: 'css/[name].css',
|
||||
chunkFilename: '[id].css',
|
||||
}),
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: path.resolve(__dirname, 'static'),
|
||||
to: path.resolve(__dirname, '../priv/static'),
|
||||
},
|
||||
]),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
"../webfonts/fa-brands-400.eot": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot"),
|
||||
"../webfonts/fa-brands-400.woff2": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2"),
|
||||
"../webfonts/fa-brands-400.woff": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff"),
|
||||
"../webfonts/fa-brands-400.ttf": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf"),
|
||||
"../webfonts/fa-brands-400.svg": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.svg"),
|
||||
"../webfonts/fa-regular-400.eot": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot"),
|
||||
"../webfonts/fa-regular-400.woff2": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2"),
|
||||
"../webfonts/fa-regular-400.woff": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff"),
|
||||
"../webfonts/fa-regular-400.ttf": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.ttf"),
|
||||
"../webfonts/fa-regular-400.svg": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.svg"),
|
||||
"../webfonts/fa-solid-900.eot": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot"),
|
||||
"../webfonts/fa-solid-900.woff2": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2"),
|
||||
"../webfonts/fa-solid-900.woff": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff"),
|
||||
"../webfonts/fa-solid-900.ttf": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.ttf"),
|
||||
"../webfonts/fa-solid-900.svg": path.resolve(__dirname, "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.svg"),
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
|
@ -11,7 +11,7 @@ config :core,
|
|||
ecto_repos: [Core.Repo]
|
||||
|
||||
# Configures the endpoint
|
||||
config :core, CoreWeb.Endpoint,
|
||||
config :core, AppWeb.Endpoint,
|
||||
url: [host: "localhost"],
|
||||
secret_key_base: "kNJbLKCmuZYSK99S55+DmirA2TlmOxzs/xz3xnlXtOhQCoBMmYRabaRLTXkcsw5d",
|
||||
render_errors: [view: CoreWeb.ErrorView, accepts: ~w(html json), layout: false],
|
||||
|
|
|
@ -15,20 +15,20 @@ config :core, Core.Repo,
|
|||
# The watchers configuration can be used to run external
|
||||
# watchers to your application. For example, we use it
|
||||
# with webpack to recompile .js and .css sources.
|
||||
config :core, CoreWeb.Endpoint,
|
||||
http: [port: 4000],
|
||||
debug_errors: true,
|
||||
code_reloader: true,
|
||||
check_origin: false,
|
||||
watchers: [
|
||||
node: [
|
||||
"node_modules/webpack/bin/webpack.js",
|
||||
"--mode",
|
||||
"development",
|
||||
"--watch-stdin",
|
||||
cd: Path.expand("../assets", __DIR__)
|
||||
]
|
||||
]
|
||||
# config :core, CoreWeb.Endpoint,
|
||||
# http: [port: 4000],
|
||||
# debug_errors: true,
|
||||
# code_reloader: true,
|
||||
# check_origin: false,
|
||||
# watchers: [
|
||||
# node: [
|
||||
# "node_modules/webpack/bin/webpack.js",
|
||||
# "--mode",
|
||||
# "development",
|
||||
# "--watch-stdin",
|
||||
# cd: Path.expand("../assets", __DIR__)
|
||||
# ]
|
||||
# ]
|
||||
|
||||
# ## SSL Support
|
||||
#
|
||||
|
|
|
@ -9,7 +9,7 @@ use Mix.Config
|
|||
# manifest is generated by the `mix phx.digest` task,
|
||||
# which you should run after static files are built and
|
||||
# before starting your production server.
|
||||
config :core, CoreWeb.Endpoint,
|
||||
config :core, AppWeb.Endpoint,
|
||||
url: [host: "example.com", port: 80],
|
||||
cache_static_manifest: "priv/static/cache_manifest.json"
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ secret_key_base =
|
|||
You can generate one by calling: mix phx.gen.secret
|
||||
"""
|
||||
|
||||
config :core, CoreWeb.Endpoint,
|
||||
config :core, AppWeb.Endpoint,
|
||||
http: [
|
||||
port: String.to_integer(System.get_env("PORT") || "4000"),
|
||||
transport_options: [socket_opts: [:inet6]]
|
||||
|
|
|
@ -14,7 +14,7 @@ config :core, Core.Repo,
|
|||
|
||||
# We don't run a server during test. If one is required,
|
||||
# you can enable the server option below.
|
||||
config :core, CoreWeb.Endpoint,
|
||||
config :core, AppWeb.Endpoint,
|
||||
http: [port: 4002],
|
||||
server: false
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ defmodule CoreWeb.Router do
|
|||
plug :fetch_flash
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
plug :put_layout, {CoreWeb.LayoutView, :app}
|
||||
end
|
||||
|
||||
pipeline :api do
|
||||
|
@ -22,20 +21,4 @@ defmodule CoreWeb.Router do
|
|||
live_dashboard "/dashboard", metrics: CoreWeb.Telemetry
|
||||
end
|
||||
end
|
||||
|
||||
if Mix.env == :dev do
|
||||
# If using Phoenix
|
||||
forward "/sent_emails", Bamboo.SentEmailViewerPlug
|
||||
end
|
||||
|
||||
scope "/", Content do
|
||||
pipe_through :browser
|
||||
|
||||
get "/", PostsController, :index
|
||||
end
|
||||
|
||||
Application.get_env(:core, :router_forwards, [])
|
||||
|> Enum.map(fn {router, path} ->
|
||||
forward path, router
|
||||
end)
|
||||
end
|
||||
|
|
|
@ -49,10 +49,9 @@ defmodule CoreWeb.Helpers do
|
|||
def styled_input(f, field, opts \\ [], options \\ nil, block_list \\ []) do
|
||||
{content, _} = Keyword.pop(block_list, :do, "")
|
||||
{type, rest_opts} = Keyword.pop(opts, :type, input_type(f, field))
|
||||
{icon, rest_opts} = Keyword.pop(rest_opts, :icon, "")
|
||||
{classes, rest_opts} = Keyword.pop(rest_opts, :class, default_classes_for_type(type))
|
||||
{label_text, rest_opts} = Keyword.pop(rest_opts, :label)
|
||||
{input_helper, rest_opts} = Keyword.pop(rest_opts, :input_helper, input_type(f, field))
|
||||
{input_helper, _rest_opts} = Keyword.pop(rest_opts, :input_helper, input_type(f, field))
|
||||
|
||||
error_classes =
|
||||
if Keyword.get_values(f.errors, field) |> Enum.any?() do
|
||||
|
@ -112,11 +111,11 @@ defmodule CoreWeb.Helpers do
|
|||
"""
|
||||
end
|
||||
|
||||
defp do_styled_input_tag(type, input_helper, f, field, nil, opts, classes, error_classes) do
|
||||
defp do_styled_input_tag(_type, input_helper, f, field, nil, opts, classes, error_classes) do
|
||||
apply(Phoenix.HTML.Form, input_helper, [f, field, opts ++ [class: Enum.join([classes, error_classes], " ")]])
|
||||
end
|
||||
|
||||
defp do_styled_input_tag(type, input_helper, f, field, options, opts, classes, error_classes) do
|
||||
defp do_styled_input_tag(_type, input_helper, f, field, options, opts, classes, error_classes) do
|
||||
apply(Phoenix.HTML.Form, input_helper, [f, field, options, opts ++ [class: Enum.join([classes, error_classes], " ")]])
|
||||
end
|
||||
|
||||
|
|
|
@ -1,39 +1,3 @@
|
|||
defmodule CoreWeb.LayoutView do
|
||||
use CoreWeb, :view
|
||||
|
||||
def title(view_module, template, assigns) do
|
||||
delegate_with_default(view_module, :title, [view_module, template, assigns], I18n.t!("en", "site.title"))
|
||||
end
|
||||
|
||||
def excerpt(view_module, template, assigns) do
|
||||
delegate_with_default(view_module, :excerpt, [view_module, template, assigns], I18n.t!("en", "site.excerpt"))
|
||||
end
|
||||
|
||||
def feed_tag(conn, view_module, view_template, assigns) do
|
||||
delegate_with_default(view_module, :feed_tag, [conn, view_module, view_template, assigns], nil)
|
||||
end
|
||||
|
||||
defp delegate_with_default(nil, _, _, default), do: default
|
||||
defp delegate_with_default(view_module, function_name, args, default) do
|
||||
sibling_layout = sibling_layout_view(view_module)
|
||||
if function_exported?(sibling_layout, function_name, args |> Enum.count()) do
|
||||
apply(sibling_layout, function_name, args)
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
defp sibling_layout_view(view_module) do
|
||||
view_module
|
||||
|> parent_module()
|
||||
|> Module.concat("LayoutView")
|
||||
end
|
||||
|
||||
defp parent_module(mod) do
|
||||
[_|tail] = Module.split(mod) |> Enum.reverse()
|
||||
|
||||
tail
|
||||
|> Enum.reverse()
|
||||
|> Module.concat()
|
||||
end
|
||||
end
|
||||
|
|
|
@ -47,7 +47,7 @@ defmodule Core.MixProject do
|
|||
{:phoenix, "~> 1.5.3"},
|
||||
{:phoenix_ecto, "~> 4.1"},
|
||||
{:ecto_sql, "~> 3.4"},
|
||||
{:linguist, "0.3.0"},
|
||||
{:linguist, "0.3.1"},
|
||||
{:postgrex, ">= 0.0.0"},
|
||||
{:phoenix_html, "~> 2.11"},
|
||||
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
||||
|
@ -73,7 +73,7 @@ defmodule Core.MixProject do
|
|||
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
|
||||
"ecto.reset": ["ecto.drop", "ecto.setup"],
|
||||
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
|
||||
"npm.install": ["cmd npm install --prefix assets"],
|
||||
"npm.install": [],
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,31 +1,3 @@
|
|||
defmodule CoreWeb.LayoutViewTest do
|
||||
use CoreWeb.ConnCase, async: true
|
||||
|
||||
import CoreWeb.LayoutView
|
||||
|
||||
describe "title/3" do
|
||||
def default_title do
|
||||
I18n.t! "en", "site.title"
|
||||
end
|
||||
|
||||
test "for nil" do
|
||||
assert title(nil, nil, nil) =~ default_title()
|
||||
end
|
||||
end
|
||||
|
||||
describe "excerpt/3" do
|
||||
def default_excerpt do
|
||||
I18n.t! "en", "site.excerpt"
|
||||
end
|
||||
|
||||
test "for nil" do
|
||||
assert excerpt(nil, nil, nil) =~ default_excerpt()
|
||||
end
|
||||
end
|
||||
|
||||
describe "feed_tag/4" do
|
||||
test "for nil" do
|
||||
assert feed_tag(nil, nil, nil, nil) == nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,7 +29,7 @@ config :app, AppWeb.Endpoint,
|
|||
url: [host: "localhost"],
|
||||
secret_key_base: "r2eN53mJ9RmlGz9ZQ7xf43P3Or59aaO9rdf5D3hRcsuiH44pGW9kPGfl5mt9N1Gi",
|
||||
render_errors: [view: AppWeb.ErrorView, accepts: ~w(html json), layout: false],
|
||||
pubsub_server: AppWeb.PubSub,
|
||||
pubsub_server: App.PubSub,
|
||||
live_view: [signing_salt: "g5ltUbnQ"]
|
||||
|
||||
# Configure Mix tasks and generators
|
||||
|
@ -67,14 +67,7 @@ config :content, Content.Endpoint,
|
|||
config :admin,
|
||||
ecto_repos: [Admin.Repo]
|
||||
|
||||
config :core,
|
||||
router_forwards: [
|
||||
{Content.Router, "/pages"},
|
||||
{AuthWeb.Router, "/auth"},
|
||||
{Admin.Router, "/admin"},
|
||||
{AppWeb.Router, "/app"},
|
||||
],
|
||||
email_from: "example@example.org"
|
||||
config :core, email_from: "example@example.org"
|
||||
|
||||
config :content,
|
||||
generators: [context_app: false]
|
||||
|
@ -82,7 +75,7 @@ config :content,
|
|||
config :content, Content.Endpoint, server: false
|
||||
config :auth_web, AuthWeb.Endpoint, server: false
|
||||
config :admin, Admin.Endpoint, server: false
|
||||
config :app, AppWeb.Endpoint, server: false
|
||||
config :app, CoreWeb.Endpoint, server: false
|
||||
|
||||
import_config "../apps/*/config/config.exs"
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use Mix.Config
|
|||
# The watchers configuration can be used to run external
|
||||
# watchers to your application. For example, we use it
|
||||
# with webpack to recompile .js and .css sources.
|
||||
config :app, App.Endpoint,
|
||||
config :app, AppWeb.Endpoint,
|
||||
http: [port: 4000],
|
||||
debug_errors: true,
|
||||
code_reloader: true,
|
||||
|
@ -46,7 +46,7 @@ config :app, App.Endpoint,
|
|||
# different ports.
|
||||
|
||||
# Watch static and templates for browser reloading.
|
||||
config :app, App.Endpoint,
|
||||
config :app, AppWeb.Endpoint,
|
||||
live_reload: [
|
||||
patterns: [
|
||||
~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
|
||||
|
|
10
mix.lock
|
@ -3,7 +3,7 @@
|
|||
"bcrypt_elixir": {:hex, :bcrypt_elixir, "1.1.1", "6b5560e47a02196ce5f0ab3f1d8265db79a23868c137e973b27afef928ed8006", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "10f658be786bd2daaadcd45cc5b598da01d5bbc313da4d0e3efb2d6a511d896d"},
|
||||
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
|
||||
"certifi": {:hex, :certifi, "2.5.2", "b7cfeae9d2ed395695dd8201c57a2d019c0c43ecaf8b8bcb9320b40d6662f340", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "3b3b5f36493004ac3455966991eaf6e768ce9884693d9968055aeeeb1e575040"},
|
||||
"cldr_utils": {:hex, :cldr_utils, "2.9.1", "be714403abe1a7abed5ee4f7dd3823a9067f96ab4b0613a454177b51ca204236", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "6cba0a485f57feb773291ca1816469ddd887e22d73d9b12a1b207d82a67a4e71"},
|
||||
"cldr_utils": {:hex, :cldr_utils, "2.11.0", "1822c5b246639aa106bb8aea674de183efe132f1bda23aa224000bfe6ee8e08d", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "79451992a1617f0b9c06c7ae1dd5ffcf3e6ae6a616bb14dea86f7ee142db71d0"},
|
||||
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
|
||||
"comeonin": {:hex, :comeonin, "4.1.2", "3eb5620fd8e35508991664b4c2b04dd41e52f1620b36957be837c1d7784b7592", [:mix], [{:argon2_elixir, "~> 1.2", [hex: :argon2_elixir, repo: "hexpm", optional: true]}, {:bcrypt_elixir, "~> 0.12.1 or ~> 1.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: true]}, {:pbkdf2_elixir, "~> 0.12", [hex: :pbkdf2_elixir, repo: "hexpm", optional: true]}], "hexpm", "d8700a0ca4dbb616c22c9b3f6dd539d88deaafec3efe66869d6370c9a559b3e9"},
|
||||
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"},
|
||||
|
@ -13,10 +13,12 @@
|
|||
"crontab": {:hex, :crontab, "1.1.10", "dc9bb1f4299138d47bce38341f5dcbee0aa6c205e864fba7bc847f3b5cb48241", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "1347d889d1a0eda997990876b4894359e34bfbbd688acbb0ba28a2795ca40685"},
|
||||
"db_connection": {:hex, :db_connection, "2.2.2", "3bbca41b199e1598245b716248964926303b5d4609ff065125ce98bcd368939e", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "642af240d8a8affb93b4ba5a6fcd2bbcbdc327e1a524b825d383711536f8070c"},
|
||||
"decimal": {:hex, :decimal, "1.9.0", "83e8daf59631d632b171faabafb4a9f4242c514b0a06ba3df493951c08f64d07", [:mix], [], "hexpm", "b1f2343568eed6928f3e751cf2dffde95bfaa19dd95d09e8a9ea92ccfd6f7d85"},
|
||||
"dialyxir": {:hex, :dialyxir, "1.0.0", "6a1fa629f7881a9f5aaf3a78f094b2a51a0357c843871b8bc98824e7342d00a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "aeb06588145fac14ca08d8061a142d52753dbc2cf7f0d00fc1013f53f8654654"},
|
||||
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"},
|
||||
"ecto": {:hex, :ecto, "3.4.6", "08f7afad3257d6eb8613309af31037e16c36808dfda5a3cd0cb4e9738db030e4", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6f13a9e2a62e75c2dcfc7207bfc65645ab387af8360db4c89fee8b5a4bf3f70b"},
|
||||
"ecto_sql": {:hex, :ecto_sql, "3.4.4", "d28bac2d420f708993baed522054870086fd45016a9d09bb2cd521b9c48d32ea", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "edb49af715dd72f213b66adfd0f668a43c17ed510b5d9ac7528569b23af57fe8"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm", "d522695b93b7f0b4c0fcb2dfe73a6b905b1c301226a5a55cb42e5b14d509e050"},
|
||||
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
|
||||
"ex_cldr": {:hex, :ex_cldr, "2.13.0", "742f14a4afcfea61a190d603d8e555d2c91d71e4e8fc2520d5dc35616969e225", [:mix], [{:cldr_utils, "~> 2.3", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:gettext, "~> 0.13", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "5e4cf3e945ee60156a3342e2a762f69036ffbe1f80520cc88592d68f12c5db55"},
|
||||
"ex_prompt": {:hex, :ex_prompt, "0.1.5", "b136642d0962f8ea37b3c9fa185ad1f42c71c3b9c6c3950f0358d7f3d2db2970", [:mix], [], "hexpm", "ad19a404708c9c7b05d36090b2d074ceafbed248a8de1a22d45a05ebe6994b83"},
|
||||
"excoveralls": {:hex, :excoveralls, "0.13.0", "4e1b7cc4e0351d8d16e9be21b0345a7e165798ee5319c7800b9138ce17e0b38e", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "fe2a56c8909564e2e6764765878d7d5e141f2af3bc8ff3b018a68ee2a218fced"},
|
||||
|
@ -24,7 +26,7 @@
|
|||
"floki": {:hex, :floki, "0.25.0", "b1c9ddf5f32a3a90b43b76f3386ca054325dc2478af020e87b5111c19f2284ac", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "631f4e627c46d5ecd347df5a2accdaf0621c77c3693c5b75a8ad58e84c61f242"},
|
||||
"gen_stage": {:hex, :gen_stage, "1.0.0", "51c8ae56ff54f9a2a604ca583798c210ad245f415115453b773b621c49776df5", [:mix], [], "hexpm", "1d9fc978db5305ac54e6f5fec7adf80cd893b1000cf78271564c516aa2af7706"},
|
||||
"gen_state_machine": {:hex, :gen_state_machine, "2.1.0", "a38b0e53fad812d29ec149f0d354da5d1bc0d7222c3711f3a0bd5aa608b42992", [:mix], [], "hexpm", "ae367038808db25cee2f2c4b8d0531522ea587c4995eb6f96ee73410a60fa06b"},
|
||||
"gettext": {:hex, :gettext, "0.18.0", "406d6b9e0e3278162c2ae1de0a60270452c553536772167e2d701f028116f870", [:mix], [], "hexpm", "c3f850be6367ebe1a08616c2158affe4a23231c70391050bf359d5f92f66a571"},
|
||||
"gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"},
|
||||
"hackney": {:hex, :hackney, "1.16.0", "5096ac8e823e3a441477b2d187e30dd3fff1a82991a806b2003845ce72ce2d84", [:rebar3], [{:certifi, "2.5.2", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.1", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.0", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.6", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "3bf0bebbd5d3092a3543b783bf065165fa5d3ad4b899b836810e513064134e18"},
|
||||
"html_entities": {:hex, :html_entities, "0.5.1", "1c9715058b42c35a2ab65edc5b36d0ea66dd083767bef6e3edb57870ef556549", [:mix], [], "hexpm", "30efab070904eb897ff05cd52fa61c1025d7f8ef3a9ca250bc4e6513d16c32de"},
|
||||
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.0.1", "2572e7122c78ab7e57b613e7c7f5e42bf9b3c25e430e32f23f1413d86db8a0af", [:mix], [{:mochiweb, "~> 2.12.2", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm", "c334e2835e094fb9c04658bd4cfc7533fa51a8f56f11343c57ab9cb2a01d8613"},
|
||||
|
@ -32,7 +34,7 @@
|
|||
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
|
||||
"kaffy": {:hex, :kaffy, "0.9.0", "bef34c9729f6a3af4d0dea8eede8bcb9e11371a83ac9a8b393991bce81839517", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.11", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm", "d18ff57b8e68feb433aed11e71510cd357abc7034e75358af5deff7d0d4c6ed3"},
|
||||
"libring": {:hex, :libring, "1.5.0", "44313eb6862f5c9168594a061e9d5f556a9819da7c6444706a9e2da533396d70", [:mix], [], "hexpm", "04e843d4fdcff49a62d8e03778d17c6cb2a03fe2d14020d3825a1761b55bd6cc"},
|
||||
"linguist": {:hex, :linguist, "0.3.0", "2984dfce6720d1212ddd7bba82496f92627a39aecd4d32c7016ec00393e1f925", [:mix], [{:ex_cldr, "~> 2.0", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.0", [hex: :yaml_elixir, repo: "hexpm", optional: false]}], "hexpm", "1923876545db22b63334c9d203ef56397a2946daa018117767b068f856be41e4"},
|
||||
"linguist": {:hex, :linguist, "0.3.1", "8ce81114691be8ef4a122e7f57bd1842bc96b1f5650b66b246d7035238cab69d", [:mix], [{:ex_cldr, "~> 2.0", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.0", [hex: :yaml_elixir, repo: "hexpm", optional: false]}], "hexpm", "5b06f97912e298f60dd00bc6a588b1fe1ec8838b268e4fdbf4443a25511f0614"},
|
||||
"meck": {:hex, :meck, "0.8.13", "ffedb39f99b0b99703b8601c6f17c7f76313ee12de6b646e671e3188401f7866", [:rebar3], [], "hexpm", "d34f013c156db51ad57cc556891b9720e6a1c1df5fe2e15af999c84d6cebeb1a"},
|
||||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
||||
"mime": {:hex, :mime, "1.4.0", "5066f14944b470286146047d2f73518cf5cca82f8e4815cf35d196b58cf07c47", [:mix], [], "hexpm", "75fa42c4228ea9a23f70f123c74ba7cece6a03b1fd474fe13f6a7a85c6ea4ff6"},
|
||||
|
@ -69,5 +71,5 @@
|
|||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.5.0", "8516502659002cec19e244ebd90d312183064be95025a319a6c7e89f4bccd65b", [:rebar3], [], "hexpm", "d48d002e15f5cc105a696cf2f1bbb3fc72b4b770a184d8420c8db20da2674b38"},
|
||||
"xml_builder": {:hex, :xml_builder, "2.1.2", "90cb9ad382958934c78c6ddfbe6d385a8ce147d84b61cbfa83ec93a169d0feab", [:mix], [], "hexpm", "b89046041da2fbc1d51d31493ba31b9d5fc6223c93384bf513a1a9e1df9ec081"},
|
||||
"yamerl": {:hex, :yamerl, "0.8.0", "8214cfe16bbabe5d1d6c14a14aea11c784b9a21903dd6a7c74f8ce180adae5c7", [:rebar3], [], "hexpm", "010634477bf9c208a0767dcca89116c2442cf0b5e87f9c870f85cd1c3e0c2aab"},
|
||||
"yaml_elixir": {:hex, :yaml_elixir, "2.4.0", "2f444abc3c994c902851fde56b6a9cb82895c291c05a0490a289035c2e62ae71", [:mix], [{:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "4e25a6d5c873e393689c6f1062c5ec90f6cd1be2527b073178ae37eae4c78bee"},
|
||||
"yaml_elixir": {:hex, :yaml_elixir, "2.5.0", "45de762be6d75fa5a8b5f44ddff8c30f64c26526eab5b1d72e36d616007b7796", [:mix], [{:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "80fe4e43f05582f2a90f2dcd73fc6171fbd65f2e6836f71fe4ce2154ef358c36"},
|
||||
}
|
||||
|
|