Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deploy a jekyll site locally with css, js and background images included?

I've been trying to load my octopress site (based on jekyll) to my local network. There is no server, I just want it available locally on a shared folder.

Every time i deploy it to a local folder the css and js and background image links are broken.

The available options such as rsync, github and heroku all require ssh's and passwords. This can be found here: http://octopress.org/docs/deploying/

Is there a rake option that helps with this?

SOLVED:

Kikito, Thank you very much for the guidance.

I just implemented it and forked a git repository. There is one problem, though. I have used this technique to host the same site on Dropbox Public, a local directory and a web host. I had to add an extra / and the slashes add up as links are clicked. Here is the repo and dropbox link:

https://github.com/originalsurfmex/jekyll-relative-bootstrap

Everything works as you say, but I think that if you or others glance at the partials and links in the layouts you will have a better idea.

like image 888
user1026169 Avatar asked Nov 02 '11 17:11

user1026169


4 Answers

Automatic way:

for css/js file:

{% assign lvl = page.url | append:'X' | split:'/' | size %}
{% capture relative %}{% for i in (3..lvl) %}../{% endfor %}{% endcapture %}

<link href="{{ relative }}css/main.css" rel="stylesheet" />
<script src="{{ relative }}scripts/jquery.js"></script>

for other files:

in _config.yml set

url: http://www.yourdomain.com

add canonical link element:

<link rel="canonical" href="{{ site.url }}{{ page.url }}" />

in one of your js file, add:

var relative = null;
if (location.protocol==='file:') {
    relative = Array($('link[rel="canonical"]').attr('href').match(/\//g).length-2).join('../');
    if (relative == '') relative = './';
}
function to_relative(link, index) {
    if (!relative) return link;
    var hash = link ? link.match(/#.*$/) : null;
    if (hash) link = link.replace(/#.*$/, '');
    return link?(link.replace(/^\//, relative)+(index?(link.substr(-1)=='/'?'index.html':''):'')+(hash?hash[0]:'')):null;
}

$(function(){
    if (relative) {
        $('a').attr('href', function(a,b){return to_relative(b, true);});
        $('img').attr('src', function(a,b){return to_relative(b, false);});
    }
});

for other aspects, use jQuery to manipulate them.

like image 158
caiguanhao Avatar answered Nov 02 '22 12:11

caiguanhao


The problem is that you are using absolute paths to get to some of your resources. If you want to deploy the site anywhere in the network, then you need to make those relative.

In my case, what I do is to define an (optional) setting called root in the pages/posts that need it, pointing to the "relative root" of the project. For example, on a page located in about/index.html, the root will be ../, since there is only one level "up":

---
title: My Page title
root: "../"
---

Pages further away in the directories will need more dots: ../../, ../../../, and so on. Pages in the root folder (like index.html) don't need a root.

Then I use that setting to generate all the paths.

If I'm on the page or post itself, and I need to refer to a local image or another page, use page.root or post.root:

<img src="{{ post.root }}images/happy.png" />
<a href="{{ post.root }}2010/01/01/another_post>Relative link to another post</a>

It's possible to make the reference directly (../images/happy.png) but this works better when you are creating the site, and you are still unsure about the definitive paths of each page.

I have all the css and js included in one partial file inside _includes. It creates a variable called root to make sure it works with both pages and posts:

{% capture root %}{% if page.root %}{{ page.root }}{% else %}{{ post.root }}{% endif %}{%endcapture%}

<script type="text/javascript" src="{{ root }}js/jquery-min.js"></script>
<link rel="stylesheet" type="text/css" href="{{ root }}/css/style.css" />

That's pretty much it.

like image 22
kikito Avatar answered Nov 02 '22 12:11

kikito


If you can live with having to generate your site for a specific folder, using the html <base /> tag may be more straightforward. With all asset paths relative to your root folder, add the following to your default layout:

<base href="{{ site.baseurl }}" />

Then use the jekyll --base-url <folder> <folder> to deploy your jekyll site to <folder> with the baseurl set up correctly.

Note that this also works without changes with the built-in WEBrick server. Start with jekyll --server and do not specify a custom --base-url.

Update: as gimpf points out in the comment, this will not work as expected with anchor links. Those will point to the base URL instead of the current page. There are workarounds using JavaScript, e.g. rewrite anchor hrefs with jQuery:

$().ready(function() {
  $("a[href^='\#']").each(function(){
    this.href=location.href.split("#")[0]+'#'+this.href.substr(this.href.indexOf('#')+1);
  });
});
like image 5
kynan Avatar answered Nov 02 '22 12:11

kynan


There is an issue on the Jekyll's github that deals with this. Putting _config.yml:

url: "<your domain>"

and then using {{ site.url }} will return the url. So for example, to refer to the /css/styles.css file from a page's header:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us">  
  <head>
      <...>
      <link rel="stylesheet" href="{{ site.url }}/css/style.css" type="text/css" />
      <...>
  </head>
  <body>
     ...
  </body>
</html>
like image 3
ivotron Avatar answered Nov 02 '22 11:11

ivotron