Trying to setup pagination with data, where {{ title }} in <head><title>{{ title }}</title></head> is the title of the current page as defined in projects.json
Assumed this could be done:
# main.njk
<head>
<title>{{ title }}</title>
</head>
# page.njk
---
layout: main.njk
pagination:
data: projects
size: 1
alias: project
permalink: "work/{{ project.title | slug }}/"
title: {{ project.title }}
Might have misunderstood some fundamentals but {{ title }} renders out as [object, object] instead. Permalink works fine...
Now eleventyComputed can be used
# main.njk
<head>
<title>{{ title }}</title>
</head>
# page.njk
---
layout: main.njk
pagination:
data: projects
size: 1
alias: project
permalink: "work/{{ project.title | slug }}/"
eleventyComputed:
title: "{{ project.title }}"
The project title can actually be accessed with {{ project.title }} in the master template main.njk, as with any other project data defined for that project in projects.json.
For any other page (not defined as an object in projects.json), a conditional statement can be used:
<title>{{ project.title if project.title else title}}</title>
So that:
# main.njk
<head>
<title>{{ project.title if project.title else title}}</title>
</head>
# page.njk
---
layout: main.njk
pagination:
data: projects
size: 1
alias: project
permalink: "work/{{ project.title | slug }}/"
---
# other_page.njk
---
layout: main.njk
title: Other Page
---
# projects.json
[
{
"title": "Project 1"
},
{
"title": "Project 2"
}
]
Outputs:
# work/project-1/
<head>
<title>Project 1</title>
</head>
# work/project-2/
<head>
<title>Project 2</title>
</head>
# other-page/
<head>
<title>Other Page</title>
</head>
In a njk file, you generally cannot use data variables or template syntax in the frontmatter.
The permalink variable is an exception.
See the official Eleventy documentation about permalink
To solve your issue, you could either:
hard-code your title in your page.njk
use a javascript .11ty.js templating file, either to replace page.njk or main.njk, or as a layout to main.njk.
.11ty.js files can generally use data variables in the frontmatter.
e.g. of a .11ty.js file with a variable in the frontmatter:
let thing = "whatever";
class Sample {
data() {// data() is the .11ty.js equivalent of frontmatter
return {
myCustomFrontmatterVariable: thing,
};
}
render(data){
return data.content;
}
}
module.exports = Sample;
Related
I have a custom widget:
module.exports = {
extend: 'apostrophe-widgets',
label: 'Banner',
addFields: [
{
name: 'bannerImg',
type: 'attachment',
label: 'Picture',
def: 'http://via.placeholder.com/350x150'
}
]
};
And widget view:
<img class="logo" src="{{ apos.attachments.url(data.widget.bannerImg) }}" />
If I load image It's Ok I see it. But I don't have the default value. Also can I choose file from gallery without upload?
I spent a half of the day and found the solution:
as answered in: How to define widgets with default values in Apostrophe CMS
{% if apos.areas.isEmpty(data.widget, 'bannerImg') %}
<h1>Default Value</h1>
{% endif %}
{{ apos.singleton(data.widget, 'bannerImg', 'apostrophe-images', { limit: 1 }) }}
And also if we want to get href of this images:
{{ apos.attachments.url(apos.images.first(data.widget.bannerImg)) }}
Also in index.js I changed on:
{
name: 'bannerImg',
type: 'singleton',
label: 'Banner',
widgetType: 'apostrophe-images',
options: {
limit: 1
}
},
In Grunt I used to use a plugin called env. That would allow me to define an environment in specific build. I had 3 builds. One was DEV which would use all the files split up individually. PROD would concat everything and RELEASE would concat and uglify. I'm looking to do the same in Gulp. I do see a preprocessor for Gulp but nothing to define environment.
The question is. What can I do? Obviously I don't want to define all JS files all the time, and I don't want 3 different HTML pages with different script tags.
In my HTML I would have something like this:
<!-- #if NODE_ENV == 'DEVELOPMENT' -->
<script src="js/example1.js" type="text/javascript"></script>
<script src="js/example2.js" type="text/javascript"></script>
<script src="js/example3.js" type="text/javascript"></script>
<!-- #endif -->
<!-- #if NODE_ENV == 'PRODUCTION' -->
<script src="js/project.js" type="text/javascript"></script>
<!-- #endif -->
<!-- #if NODE_ENV == 'RELEASE' -->
<script src="js/project.min.js" type="text/javascript"></script>
<!-- #endif -->
And my grunt plugins would look like this:
env: {
dev: {
NODE_ENV: 'DEVELOPMENT'
},
prod: {
NODE_ENV: 'PRODUCTION'
},
release: {
NODE_ENV: 'RELEASE'
}
},
preprocess: {
options: {
context: {
name: '<%= pkg.outputName %>',
version: '<%= pkg.version %>',
port: '<%= pkg.port %>'
}
},
dev: {
src: 'index.html',
dest: '<%= pkg.outputFolder %>/index.html'
},
prod: {
src: 'index.html',
dest: '<%= pkg.outputFolder %>/index.html'
},
release: {
src: 'index.html',
dest: '<%= pkg.outputFolder %>/index.html'
}
},
You should probably use gulp-preprocess and do stuff like this in gulp
var preprocess = require('gulp-preprocess');
.pipe(preprocess({context: { NODE_ENV: 'PRODUCTION', RELEASE_TAG: '2.6.4', DEBUG: false}}))
with stuff like this in your html
<!-- #if NODE_ENV='DEVELOPMENT' -->
<a href="test?v<!-- #echo RELEASE_TAG -->" />
<!-- #endif -->
Here is how I accomplished what I think you want.
I have set up a folder that contains html pages to be preprocessed.
Within that folder I have folders corresponding to each page where I store html fragments and a json file.
Each JSON file has variables defining page assets for a specific page.
For example, say my page is index.html. It looks something like this:
<html>
<head>
... Meta stuff title etc ...
<!-- #ifdef pagecss1 -->
<link href="<!-- #echo pagecss1 -->" rel="stylesheet">
<!-- #endif -->
<!-- #ifdef pagecss2 -->
<link href="<!-- #echo pagecss2 -->" rel="stylesheet">
<!-- #endif -->
</head>
/// so on - same stuff with scripts at bottom
In my JSON file for that page I either have pagecss1 define or not.
Then I use gulp.watch.
I don't want to write out the whole thing, but the upshot is every time any of the files in the sub folders change a function intercepts the already existing global context variable, and reads the JSON file for that page. Then I use node.util._extend to overwrite the variables with page specific variables. I then pass the changed object to the preprocessor task as the context. It's all lightening quick and returns a callback that livereload know which page to reload.
I wrote this on mobile, so I may come back to edit for clarity, but solving this riddle saved me an incredible amount of time and effort.
I have been trying for some time now to compile Bootstrap 3 in a Symfony 2 project on Windows. But I can't get it to work. My primary objective is to compile my very own LESS file. I called it "styles.less". In there, I want to be able to use bootstrap mixins like "make-xs-column" for example. So I need to import bootstrap.less for that.
Here is what I did so far:
In my composer.json, I added the bootstrap bundle:
{
...
"require": {
...
"twitter/bootstrap": "v3.0.3"
},
....
}
Since I want to use Bootstrap 3, I cannot use the lessphp filter, so I use the less filter instead. For that, I had to install nodejs, and then less (by running the command "npm install less -g"). Finally, I modified my config.yml like so:
assetic:
debug: "%kernel.debug%"
use_controller: false
bundles: [ JoePersonalWebSiteBundle ]
filters:
cssrewrite: ~
less:
node: "C:\\dev\\nodejs\\lessc.cmd"
node_paths:
- "C:\\dev\\nodejs\\node_modules"
apply_to: "\.less$"
Now, in my layout.html.twig, I added the following:
{% stylesheets filter='less' '#JoePersonalWebSiteBundle/Resources/less/styles.less' %}
<link rel="stylesheet" type="text/css" href="{{ asset_url }}">
{% endstylesheets %}
And in my "styles.less" file, I import"bootstrap.less" like so:
#import '../../../../../../vendor/twitter/bootstrap/less/bootstrap.less';
But I always get an error. In fact, even if my "styles.less" file is completely empty, I always get an error like this one:
[exception] 500 | Internal Server Error | Assetic\Exception\FilterException
[message] An error occurred while running:
"C:\dev\nodejs\lessc.cmd" "C:\Users\joe\AppData\Local\Temp\assDE7E.tmp"
Error Output:
[31mParseError: missing opening `{`[39m[31m in [39mC:\Users\joe\AppData\Local\Temp\assDE7E.tmp[90m on line 17, column 1:[39m
[90m16 });[39m
17 [0m[0m
[1] Assetic\Exception\FilterException: An error occurred while running:
"C:\dev\nodejs\lessc.cmd" "C:\Users\joe\AppData\Local\Temp\assDE7E.tmp"
Error Output:
[31mParseError: missing opening `{`[39m[31m in [39mC:\Users\joe\AppData\Local\Temp\assDE7E.tmp[90m on line 17, column 1:[39m
[90m16 });[39m
17 [0m[0m
I tried to create my own recess filter to use that instead of less (based on the work by boteeka found here). But that didn't work either. The less files never compile. Even an empty one, or a simple one.
Could someone please point me in the right direction? Is it possible on Windows, to compile Bootstrap 3 in a Symfony 2 project? If so, can someone give me the exact steps I should follow?
I use lessphp in windows with Bootstrap v3.0.0. The original idea is from http://mossco.co.uk/symfony-2/symfony-2-and-bootstrap-3-assetic-config-and-base-html-template-file/
I have also added to the entries for the fonts, icons.
My composer.json
"require": {
"components/jquery": "dev-master",
"leafo/lessphp": "v0.4.0",
"twbs/bootstrap": "v3.0.0",
},
For the config.yml copy 'cssembed' and 'yuicompressor' to '%kernel.root_dir%/Resources'
/java/
My config.yml
# Assetic Configuration
assetic:
debug: %kernel.debug%
use_controller: false
bundles: [ ]
java: C:\Program Files\Java\jre7\bin\java.exe
filters:
cssrewrite: ~
cssembed:
jar: %kernel.root_dir%/Resources/java/cssembed-0.4.5.jar
yui_js:
jar: %kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar
lessphp:
file: %kernel.root_dir%/../vendor/leafo/lessphp/lessc.inc.php
apply_to: "\.less$"
assets:
jquery_js:
inputs:
- "%kernel.root_dir%/../components/jquery/jquery.min.js"
filters: [?yui_js]
bootstrap_js:
inputs:
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/transition.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/alert.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/modal.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/dropdown.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/scrollspy.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/tab.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/tooltip.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/popover.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/button.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/collapse.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/carousel.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/affix.js"
filters: [?yui_js]
bootstrap_less:
inputs:
- "%kernel.root_dir%/../vendor/twbs/bootstrap/less/bootstrap.less"
filters: [lessphp, cssembed]
fonts_glyphicons_eot:
inputs:
- "%kernel.root_dir%/../vendor/twbs/bootstrap/fonts/glyphicons-halflings-regular.eot"
output: "fonts/glyphicons-halflings-regular.eot"
fonts_glyphicons_svg:
inputs:
- "%kernel.root_dir%/../vendor/twbs/bootstrap/fonts/glyphicons-halflings-regular.svg"
output: "fonts/glyphicons-halflings-regular.svg"
fonts_glyphicons_ttf:
inputs:
- "%kernel.root_dir%/../vendor/twbs/bootstrap/fonts/glyphicons-halflings-regular.ttf"
output: "fonts/glyphicons-halflings-regular.ttf"
fonts_glyphicons_woff:
inputs:
- "%kernel.root_dir%/../vendor/twbs/bootstrap/fonts/glyphicons-halflings-regular.woff"
output: "fonts/glyphicons-halflings-regular.woff"
And here my base.html.twig
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}
{% stylesheets '#bootstrap_less' combine=true %}
<link href="{{ asset_url }}" type="text/css" rel="stylesheet">
{% endstylesheets %}
{% endblock %}
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %}
{% javascripts '#jquery_js' '#bootstrap_js' filter='?yui_js' combine=true %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endblock %}
</body>
</html>
Somehow cssembed unnecessary or does not function properly and can be removed with this solution!
I'm using yeoman and grunt to build my project and grunt-css plugin for using 'cssmin' instead of 'css' built-in with grunt.js
index.html
<!-- build:css styles/styles.css -->
<link rel="stylesheet" href="styles/main.css"/>
<!-- endbuild -->
<!-- build:js scripts/scripts.js -->
<script src="scripts/vendor/jquery.min.js"></script>
<script src="scripts/vendor/handlebars-1.0.0.beta.6.js"></script>
<script src="scripts/vendor/ember-1.0.pre.min.js"></script>
<script src="scripts/main.js"></script>
<script src="scripts/routes/app-router.js"></script>
<script src="scripts/store.js"></script>
<script src="scripts/controllers/application-controller.js"></script>
<script src="scripts/models/application-model.js"></script>
<script src="scripts/views/application-view.js"></script>
<!-- endbuild -->
Gruntfile.js
rev: {
js: 'dist/scripts/**/*.js', // scripts/**/*.js
css: 'dist/styles/**/*.css', // styles/**/*.css
img: 'dist/images/**' // images/**
},
'usemin-handler': {
html: 'index.html'
},
usemin: {
html: ['dist/**/*.html'], // **/*.html
css: ['dist/**/*.css'] // **/*.css
},
rjs: {
// no minification, is done by the min task
optimize: 'none',
baseUrl: './scripts',
wrap: true
},
cssmin: {
dist: {
src: [
'app/styles/**/*.css'
],
dest: 'dist/styles/styles.css'
}
},
concat: {
dist: {
src: [
'app/scripts/**/*.js'
],
dest: 'dist/scripts/scripts.js',
separator: '/**********/\n'
}
},
min: {
dist: {
src: [
'dist/scripts/scripts.js'
],
dest: 'dist/scripts/scripts.js',
separator: '/**********/\n'
}
}
Then the build project structure is:
dist/
|__scripts/
|____04216377.scripts.js
|__styles/
|____d41d8cd9.styles.css
|__index.html
Then output index.html file
<link rel="stylesheet" href="styles/styles.css"/?>
<script src="scripts/04216377.scripts.js"></script>
As you see all went OK except renaming the revisioned styles in index.html that should be 'styles/d41d8cd9.styles.css
Anyone knows why?
And is the questionmark '?' in the line normal???
Note: for more information this is outputted in my console (no errors)
Running "rev:js" (rev) task
dist/scripts/scripts.js --- 04216377.scripts.js
Running "rev:css" (rev) task
dist/styles/styles.css --- d41d8cd9.styles.css
Running "rev:img" (rev) task
Running "usemin:html" (usemin) task
usemin:html - dist/index.html
scripts/scripts.js
was <script src="scripts/scripts.js"></script>
now <script src="scripts/04216377.scripts.js"></script>
Running "usemin:css" (usemin) task
usemin:css - dist/styles/d41d8cd9.styles.css
And no renaming has been done!
Thanks a lot guys!
I've found the problem.
I've got Yeoman 0.94 version and needs a fix on usemin task.
The ?character at <link>is a regex mistake.
You should rewrite this expression because css renaming is failing.
Found the correct workaround at https://github.com/yeoman/yeoman/issues/586
replace
content.replace(block, indent + '<link rel="stylesheet" href="' + target + '"\/?>');
with
content.replace(block, indent + '<link rel="stylesheet" href="' + target + '"/>');
If apply changes this issue is solved.
Note: apply the patch on usemin.js at /usr/local/lib/node_modules/yeoman/tasks (on OSX)
I want to implement a kind of file-browser, where the user can navigate using the folder-tree, and see the folder-content in a grid.
I want to use the same data-store for both widgets, but can't see how to achive this - the tree needs items with e.g. a children-attribute, the grid only needs those children.
because ther may be a huge dataset, I'm planning to use the jsonreststore.
i was trying with this, and got one solution like this, Please note that the grid and tree are using the same store.. Here the catch is if folder has id of fld1 then all the files under that folder should have id pattern like "fld1f1","fld1f2".
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html dir="ltr">
<head>
<style type="text/css">
body, html { font-family:helvetica,arial,sans-serif; font-size:90%; }
</style>
<script src="djlib/dojo/dojo.js" djConfig="parseOnLoad: true"></script>
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dijit/themes/claro/claro.css"/>
<link rel="stylesheet" type="text/css" href="djlib/dojox/grid/resources/Grid.css"/>
<link rel="stylesheet" type="text/css" href="djlib/dojox/grid/resources/claroGrid.css"/>
</head>
<body class=" claro ">
<div id="treeOne"></div>
<div id="gridHolder" style="height:500px"></div>
</body>
<script type="text/javascript">
s =[];
dojo.require("dijit.tree.ForestStoreModel");
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("dijit.Tree");
dojo.require("dojox.grid.DataGrid");
dojo.addOnLoad(function(){
baseStore = new dojo.data.ItemFileReadStore({
data:{
identifier: 'id',
label: 'name',
items: [
{id:'fld1',name:'folder 1', type:"folder", files:[{_reference:'fld1f1'},{_reference:'fld1f2'}]},
{id:'fld1f1',name:'file 1 of folder 1', type:"file", size:'1KB', dateLstMod:'15/15/2001'},
{id:'fld1f2',name:'file 2 of folder 1', size:'1KB', type:"file", dateLstMod:'15/15/2001'},
{id:'fld2',name:'folder 2', type:"folder", files:[{_reference:'fld2f1'},{_reference:'fld2f2'}]},
{id:'fld2f1',name:'file 1 of folder 2', size:'1KB', type:"file", dateLstMod:'15/15/2001'},
{id:'fld2f2',name:'file 2 of folder 2', size:'1KB', type:"file",dateLstMod:'15/15/2001'},
{id:'fld3',name:'folder 3', type:"folder"}
]
}
});
treeModel = new dijit.tree.ForestStoreModel({
store: baseStore,
query:{
type:'folder'
},
rootId: "root",
rootLabel: "List of folders on this drive",
childrenAttrs:['files']
})
t = new dijit.Tree({
model: treeModel
},"treeOne")
dojo.connect(t,'onClick', function(item, node, evt){
if(node.isExpandable){
updateGrid(baseStore.getValues(item,"id"));
}
})
function updateGrid(folderId){
grid.filter({
type:'file' , id:folderId+'*'
},true);
}
var gridStr = [{
cells:[
[
{ field: "name", name: "File Name", width: 'auto' },
{ field: "size", name: "Size", width: 'auto'},
{ field: "dateLstMod", name: "Date Last Modified", width: 'auto'}
]
]
}]
grid = new dojox.grid.DataGrid({
store:baseStore,
structure: gridStr,
noDataMessage:"NO DATA"
}, 'gridHolder');
grid.startup();
grid.filter({
type:'filee'
},true);
})
I think this link has the answer, you don't point the grid at the store, you create the grid and add items by iterating across the relevant children in the store
http://groups.google.com/group/dojo-interest/browse_thread/thread/af7265b19edeeb0/9fee8b5498746dd8