I am currently working on a 11ty project and really like it. But I have a problem with the links when I deploy the output. I'd like to deploy it to 2 different locations on separate servers. One of the locations is in the root directory, the other one in a sub-folder.
Is it possible to have relative links in the output?
I already tried pathPrefix, but either I don't use it properly or it just doesn't give me the result I am looking for.
.eleventy.js:
module.exports = eleventyConfig => {
...
// Include our static assets
eleventyConfig.addPassthroughCopy("images")
return {
pathPrefix: "/subfolder/",
templateFormats: ["md", "njk"],
markdownTemplateEngine: 'njk',
htmlTemplateEngine: 'njk',
passthroughFileCopy: true,
dir: {
input: 'site',
output: 'dist',
includes: 'includes',
data: 'globals',
}
}
}
When I run eleventy --config=eleventy.config.js --serve, an additional folder gets generated with the name _eleventy_redirect, including an index.html file with:
<!doctype html>
<meta http-equiv="refresh" content="0; url=/subfolder/">
<title>Browsersync pathPrefix Redirect</title>
Go to /subfolder/
When I run eleventy --config=eleventy.config.js (without the --serve), that folder isn't there.
However, either way all the links are absolute (e.g. Home is href="/"), and the site doesn't work on the server.
Is there a way to have either relative links (e.g. Home is href="./" on the root index.html and href="../" on sub pages) or at least include the subfolder in the urls (e.g. Home is href="./subfolder/")?
Not quite what I was looking for, but it helps with some parts of my issue.
The url filter normalizes absolute paths, e.g.
href="{{ "/" | url }}"
See the eleventy github for more details.
I came across the same problem and found a solution: use Liquid Template variables (which already come in Eleventy) to insert the relative part of the path.
Suppose you have:
The index.html page at the root of the directory.
The contact.html page, whose index ends up being created inside the /contact directory.
The _head.html file that imports some css's and is included in both pages.
You could do it as follows:
_head.html :
<link rel="stylesheet" href="{{ relative_prefix }}/scss/styles.min.css">
<link rel="shorstcut icon" href="{{ relative_prefix }}/favicon.ico">
index.html :
{% assign relative_prefix = '.' %}
{% include _head.html %}
<body>
...
contact.html (that turns into /contact/index.html) :
{% assign relative_prefix = '..' %}
{% include _head.html %}
<body>
...
This way, you can choose to always use relative paths, and never use absolute paths. Consequently, you can simply copy the files generated by Eleventy to several different directories and it will work for all of them. The cool thing is that the site also works on your local machine without a running server, that is, you can open the site in the browser as follows: file:///C:/myProjectDir/_site/index.html
Related
I'm currently building a Grav theme, in which a div should have the particle background from particle.js.
As stated by the setup manual, the actual function call in the js to render the particles, requires a config file in .json format
/* particlesJS.load(#dom-id, #path-json, #callback (optional)); */
particlesJS.load('particles-js', 'assets/particles.json', function() {
console.log('callback - particles.js config loaded');
});
However, I'm unsure how I can provide the path to the json file.
When I tried to pass a regular html relative path (like in the example above), the GET command in the console returned a 404 error.
When I tried a Static Asset Path using {{ url("theme://assets/particles.json") }}, the GET returned a 403 (Forbidden) error.
How can I provide the path in the external script?
Found the solution myself: Instead of providing a relative path or using the stream functions, you can provide a "semi-relative" path to the theme's asset folder (if you use one):
/user/themes/<theme-name>/assets/particles.json
EDIT: In response to the comment by #motizukilucas, I now had a look back at my code (this has been quite a while back, so I try to be as precise as possible; also I don't know if this is still the correct and most elegant way to do it).
For the .twig file of the main page that this is used in:
{% set theme_config = attribute(config.themes, config.system.pages.theme) %}
<!DOCTYPE html>
<html class="h-full" lang="{{ grav.language.getActive ?: theme_config.default_lang }}">
<head>
...
{% do assets.addJs('theme://js/vendor/particles.js', 80) %}
{% do assets.addJs('theme://js/frontend_js.js', {'priority':80, 'group':'bottom'}) %}
</head>
...
{% block bottom %}
{{ assets.js('bottom') }}
{% endblock %}
For the frontend.js file (this is where the relative path goes that I mentioned in my initial answer); in the manual this is called app.js:
/* particlesJS.load(#dom-id, #path-json, #callback (optional)); */
particlesJS.load('particles-js', '/user/themes/<theme-name>/assets/particles.json', function() {
console.log('callback - particles.js config loaded');
});
Then just place the particles.js in the //js/vendor/ folder in the theme (see relative path in the .twig file above) and your config (particles.json) in the mentioned /user/themes/<theme-name>/assets/ folder.
Hi i am using assetic in symfony 3. But i have problem my assets are defined like this:
{% stylesheets filter='cssrewrite' filter='?uglifycss'
'assets/font-awesome-4.6.3/css/font-awesome.min.css'
'assets/bootstrap-3.3.7/css/bootstrap.min.css'
...
%}
In console run php bin/console assetic:watch
After change in css or js it will generate new file but with same name for example ce9c2ef.css.
But it is problem because after deploy, css file has changes content but no filename so all people see old css...
Q: How i can change generated file name every change in css?
There is options 'output='path/filename.js' in {% stylesheets %} but there i can't add <?php echo $var; ?> or {{ var }}...
UPDATE:
assetic config:
assetic:
debug: '%kernel.debug%'
use_controller: '%kernel.debug%'
filters:
cssrewrite: ~
uglifyjs2:
bin: "%kernel.root_dir%/Resources/node_modules/uglify-js/bin/uglifyjs"
uglifycss:
bin: "%kernel.root_dir%/Resources/node_modules/uglifycss/uglifycss"
templating config:
templating:
engines: ['twig']
EDIT:
So i found solution PARTIAL solution:
To config add:
assetic:
workers:
cache_busting: ~
and after that, your file will looks like ce9c2ef-d1e35a0_filename.css in develop and ce9c2ef-d1e35a0.css in prod...
but in deploy you must clear cache first so you have 2 hashes first ce9c2ef still the same (I do not understand the point of existence) and second d1e35a0 is changing so it finally resolving problem with browser cache....
But if you make changes in css, assetic:watch compile it, but page loads old files...!
Worst bundle ever i mean that changing filename is basic thing and on the internet is so many ways how resolve it and i was tryed one after another 1 day until i finally succeed...
When you're using assetic, one way to solve your issue is by giving your assets a version in your framework:templating section of app/config.yml:
assets:
version: "%application_version%"
Then you can specify your version in your parameters.yml/parameters.yml.dist file:
parameters:
application_version: 1.0.1
Then you can load your stylesheets or javascript like so:
{% stylesheets output='css/sites.css' filter='cssrewrite'
'assets/font-awesome-4.6.3/css/font-awesome.min.css'
'assets/bootstrap-3.3.7/css/bootstrap.min.css'
...
%}
<link href="{{ asset_url }}" type="text/css" rel="stylesheet" media="all" />
{% endstylesheets %}
Now when you dump your assets, it will automatically append ?1.0.1 (or whatever version you are on" to the end of them. For example, in production you would see the following:
<link href="/css/site.css?1.0.1" type="text/css" rel="stylesheet" media="all" />
Note that there are different ways of doing naming strategies, and this can get tricky if you forget to update your assets version every time you make changes to your assets, but there are ways to improve upon that strategy. This should get you up and running though.
If you notice I didn't manually specify the uglify* filters - you can have these automatically applied by putting this in your app/config_prod.yml:
assetic:
filters:
uglifycss:
apply_to: "\.css$"
uglifyjs2:
apply_to: "\.js$"
I am working with Django 1.8 + AngularJS 1.4.5.
Django has an amazing feature to prevent modified files are cached: ManifestStaticFilesStorage.
Once a file is modified the collectstatic command recalculate and add to the filename the hash of the file.Then look for all the appearances of the url with that file and and replace the original filename with the hashed filename.
Eg:
styles.css -> styles.b8a501ed930c.css
And:
<link href="{% static 'css/styles.css' %}" rel="stylesheet">
Is compiled as:
<link href="/static/css/styles.b8a501ed930c.css" rel="stylesheet">
That is very helpful, but only rename the filenames inside the {% static %} tag.
Is there any way to add this feautre to the urls inside css/js files? For example to add a hash name to the partials html templates of angularjs.
$routeProvider.when('/mypage', {
templateUrl: "mypage.html", -> ("mypage.hashdigest.html")
controller: "MyPageController"
});
Given the following code:
$('img').mouseenter(function(){
//...
}).mouseleave(function(){
//...
});
I'd like it to be included in my articles. I'd like to avoid editing the theme if possible so to avoid forking etc.
This depends a little on which theme you use. This may be an area where we could do a better job, but do this:
In the theme, look in the
layouts/partials folder.
If you find a header.html or similar, copy this to your local layouts/partials. You can then override the content of this file only. Alternatively you can customize by copying the template used for single pages, often: layouts/_default/single.html.
bep's answer is excellent, but here are some additional details for hugo/frontend newcomers like me
1. Find a place in your HTML where to include the JS
First, one should copy the header.html or footer.html (or similar) of the Hugo theme to your layouts/partials folder. It does not necessarily have to be the header or the footer, but a file that is included in every page on your html (and that's why you would typically use the header.html or footer.html).
I got a theme that had the footer at <theme_folder>\layouts\partials\_shared\footer.html, which I then copied from the theme folder into the project layout folder <project_root>\layouts\partials\_shared\footer.html.
2. Include the script.js in the HTML
Then, I added to the bottom of footer.html
<script defer language="javascript" type="text/javascript" src="{{ "/js/myscripts.js" | urlize | relURL }}"></script>
The defer attribute can improve the page loading time a bit, and "/js/myscripts.js" is the location of my javascripts. The location is path relative to <project_root>\static\. Here are the documentation about relURL and urlize.
The example script file contains just
// myscripts.js
function myFunction(x) {
let d = new Date();
alert("Current datetime: " + d + "\nYou passed in: " + x);
}
3. Use the JS function
This is an example of using the JS function from within Hugo template (any .html belonging to the template):
{{ $somevar := "spam"}}
<button onclick="myFunction( {{ $somevar}} )">Click me</button>
Inline JS
It looks like also inline JS runs just fine; for example, adding
<script>
alert("Script loaded!");
</script>
to a template html file ran just fine. I would use this only for quick testing though, since some scripts might be needed in multiple html files, and adding the same script to multiple files would just increase your overall website filesize.
I copy themes/whatever/layouts/_default/baseof.html to layout/_default/baseof.html and add the following block at the end of the html tag:
{{ block "page-script" . }}{{ end }}
Then I can add
{{- define "page-script" -}}
<script>console.log("Hello!")</script>
{{- end -}}
in my layouts files to put in a script.
I've been trying figure out how to get a static website generator with built-in hash routing solution. I guess I could only describe it as a poor mans 'client side javascript framework with routing that works locally with out a server'.
My main goal is to avoid pages from being reloaded unnecessarily. While some pages would be refreshed, my hope is that the majority would not. Additionally, I still wanted to maintain page markup via markdown formatted pages.
I tried to do this with pure client side javascript and templates, but couldnt get any frameworks to parse markdown for me.
This is my hacked up solution perhaps some of you have a setup that works better or more elegant. Perhaps using Jekyll plus another routing framework like angular?
Note: I created a layout named 'empty' for hash routed pages because if the doctype, head, etc are duplicated then the pages will not load.
Problem: Files in other directories that load images - These files load images from their own directory, but when called via pagify.js to another directory their links are all broken
Jekyll + Pagify.js with Liquid include 'root' for relative urls (thanks to kikito):
root include:
{% capture root %}{% if page.root %}{{ page.root }}{% else %}{{ post.root }}{% endif %}{%endcapture%}
load scripts:
<script type="text/javascript" src="{{ root }}/js/jquery.js"></script>
<script type="text/javascript" src="{{ root }}/js/pagify.js"></script>
setup core html:
{% include root %}
<h1>Pagify.js<small>A jQuery plugin for single page web sites</small></h1>
<nav>
<a href='{{ root }}#about'>About</a>
<a href='{{ root }}#usage'>Usage</a>
<a href='{{ root }}#options'>Options</a>
<a href='{{ root }}#gallery'>Gallery</a>
<a href='{{ root }}#Showcase/VM'>Showcase</a>
</nav>
load script from pagify.js at end of core html:
<script>
$(document).ready(function() {
$('#page_holder').pagify({
pages: [
'about',
'usage',
'options',
'gallery',
'Showcase/VM'
],
animation: 'fadeIn',
'default': 'about',
cache: true
});
});
sample YAML heading from a hash routed page:
---
layout: empty
title : about
root: .\
---
{% include root %}
this is what the layout named 'empty.html' looks like:
{% include root %}
<div class="page-header">
<h1 class="well">{{ page.title }} <small>{{ site.tagline }}</small></h1>
</div>
{{ content }}
I created a Jekyll plugin to ease this process a bit. It takes away the need to manually specify all the pages you want to link to. Let me know what you think of it.