I have clientlibs with category abc. It contains multiple js files e.g.
abc
|-->JS
| |--->a.js
| |--->b.js
| |--->c.js
|-->js.txt[which have the paths of all three js files]
If I use something like : <cq:includeClientLib js="abc" />. This include all my js files in my script. But how can i restrict to include only two. These 3 are just example, there can be 10 or more. Does anyone has any idea how this can achive excluding creating new clientlib folder.
Thanks
You can achieve this requirement using themes functionality of clientlibs. It will require few modifications to the clientlibs structure. Let me explain it with three js files (a.js , b.js and c.js).
Let's assume b.js is not required all the time where as a.js and c.js are. You will have to create a parent clientlib with a.js and c.js. In the same clientlib create a theme folder and add a second clientlib with b.js [should have same category as parent], the structure should be as follows :
clientlibs: {
categories: [
"themeParent"
],
jcr: primaryType: "cq:ClientLibraryFolder",
js: {
jcr: primaryType: "nt:folder",
a.js: {
jcr: primaryType: "nt:file",
jcr: content: {}
},
c.js: {
jcr: primaryType: "nt:file",
jcr: content: {}
}
},
js.txt: {
jcr: primaryType: "nt:file",
jcr: content: {
//a.js and c.js
}
},
themes: {
jcr: primaryType: "nt:folder",
themeb: {
categories: [
"themeParent"
],
jcr: primaryType: "cq:ClientLibraryFolder",
js.txt: {
jcr: primaryType: "nt:file",
jcr: content: {
//b.js
}
},
b.js: {
jcr: primaryType: "nt:file",
jcr: content: {}
}
}
}
}
Themes can be selectively enabled for a clientlib using the themed flag of includeClientLib tag.
<cq:includeClientLib js="themeParent"/> : will include a.js , c.js and b.js
<cq:includeClientLib js="themeParent" themed="false"/> : will include a.js and c.js
<cq:includeClientLib js="themeParent" themed="true"/> : will only include b.js
References : How are themes applied in Adobe AEM?
You can remove the js file entry in the 'js.txt', js will be present in the path but will not be included as part of cq:include
To the best of my knowledge this is not possible. Whatever js file names you enter in the js.txt will be included when you write this <cq:includeClientLib js="abc" /> statement in your JSP.
So say if you want to include only two JS files in another JSP without creating a new clientlib the only way to do it is include the manually using full path.
like this
<script src="/etc/designs/projectname/clientlibs/js/a.js"></script>
<script src="/etc/designs/projectname/clientlibs/js/b.js"></script>
Related
I have a site with PWA img assets in
img/icons/imagename.png
I am trying to build the site with vite and vite-plugin-pwa to use it as a pwa.
The vite.config.js and the index.html are in the project root directory. Images are in img directory.
The problem is that when I run the build file places the imgs in the folder assets/imageName###.png
For example chrome192.png is placed in assets/chrome192.f25426fd.png
However, the manifest file generated upon build manifest.webmanifest still contains
src: 'img/icons/chrome192.png',
The application tab for dev tools in chrome shows {rootURL}/img/icon/chrome192.png not found. Which is expected since the bundling with vite build places it in a different folder (assets).
Why does it not update the path of the images in the generated manifest.webmanifest?
Isn't that the whole point of the vite-plugin-pwa to keep track of the filenames that change upon build.
Another issue is that I have different routes eg: html/about
Inside the about.html generated on build, the web manifest path is given as:
<link rel="manifest" href="./manifest.webmanifest">
It uses this path instead of using ../manifest.webmanifest or maybe a path from the root without the ./ such as href="./manifest.webmanifest"
My vite.config.js is shown below
import { resolve } from 'path';
import { defineConfig } from 'vite';
import { VitePWA } from 'vite-plugin-pwa'
// import legacy from '#vitejs/plugin-legacy';
export default defineConfig({
plugins: [
VitePWA({
includeAssets: ['img/icons/favicon.png', 'img/icons/maskable_icon.png' ],
manifest: {
name: 'Final Countdown',
start_url: "/",
short_name: 'Final Countdown',
description: 'Awesome countdown App',
theme_color: '#031c36',
icons: [
{
src: 'img/icons/chrome192.png',
sizes: '192x192',
type: 'image/png'
},
{
src: 'img/icons/chrome512.png',
sizes: '512x512',
type: 'image/png'
},
{
src: 'img/icons/chrome512.png',
sizes: '512x512',
type: 'image/png',
purpose: 'any maskable'
}
]
}
})
],
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
about: resolve(__dirname, 'html/about.html'),
countdownList: resolve(__dirname, 'html/countdown-list.html'),
fallback: resolve(__dirname, 'html/fallback.html'),
today: resolve(__dirname, 'html/today.html'),
formupload: resolve(__dirname, 'html/form-upload.html'),
},
},
},
});
The code is hosted at this branch if you need to take a look at the full folder
https://github.com/RDjarbeng/countdown/tree/vitePWA
I have removed the previous manifest.json file that used to work before I started using the vite-plugin-pwa, because when it was included there were two manifest files in the build instead.
Have also tried using /img/icons/... for the paths and resolve(__dirname, img/icons/chrome192.png)
How do I get the PWA manifest and icons to sync with the image build files generated by the viteJS bundler and satisfy the PWA conditions?
How do I get the paths of html files not in the root folder to use the correct path to the manifest.webmanifest?
If the icon is only being used in the webmanifest icons, those icons should go to public folder.
Create a folder named public in the root directory and move the icons for the manifest there. Vite will add these to the build without changing the file names.
Find full solution here.
https://github.com/vite-pwa/vite-plugin-pwa/issues/396
You do not need to add public/ to the names of the images in the manifest.json.
In the end the vite config, vitePWA contained
...
includeAssets: ["**/*.{png}"],
manifest: {
name: 'Final Countdown',
start_url: "/",
id: "/",
short_name: 'Final Countdown',
description: 'Awesome countdown App',
theme_color: '#031c36',
icons: [
{
src: '/img/icons/chrome192.png',
sizes: '192x192',
type: 'image/png'
},
{
src: '/img/icons/chrome512.png',
sizes: '512x512',
type: 'image/png'
},
]
},
Full path to the image:
{rootURL}/public/img/icons/chrome192.png
where {rootURL} is the root url from which the site is served
I am trying to set up a website with Svelte for the frontEnd and Sails for the backend.
My problem is that I can't display my Svelte public build as my Sails default web page.
I want to keep the organization below (or maybe something similar) and have my Svelte public build page when I go on 'http://myserver:1337' instead of having the default Sails page : file organization
PS: I am using Node: v14.4.0, Sails: v1.2.4 and Svelte: v6.14.5.
Thank you all :)
You could try something like:
Compile Svelt to build into the /public directory on Sails.js.
Open your rollup.config.js and change the path of your public/build/bundle.js and public/build.bundle.css to the public sails path, i.e. "../server/public...".
Configure /task/pipeline.js to include the compiled js and css files:
// tasks/pipeline.js
var cssFilesToInject = [
'css/**/global.css',
'css/**/bundle.css',
'css/**/*.css',
];
var jsFilesToInject = [
'js/**/bundle.js',
'js/**/*.js'
];
Create a controller to load the index file:
// router.js
'/*': { action: 'index', skipAssets: true, skipRegex: /^\/api\/.*$/ },
The excluded "/api" routes is to allow you to configure the CRUD routes.
The index controller:
module.exports = {
friendlyName: 'View homepage',
description: 'Display a compiled index page',
exits: {
success: {
statusCode: 200,
viewTemplatePath: 'pages/index'
},
},
fn: async function () {
return {};
}
};
And the index page you could include the template index.html or create your own index.ejs to load the static content, the same you configured before:
// views/templates/template.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Svelte app</title>
<link rel='icon' type='image/png' href='/favicon.png'>
<!--STYLES-->
<!--STYLES END-->
</head>
<body>
<!--TEMPLATES-->
<!--TEMPLATES END-->
<%- body %>
<!-- exposeLocalsToBrowser ( ) %>
<!--SCRIPTS-->
<!--SCRIPTS END-->
</body>
</html>
And the index.ejs:
// views/pages/index.ejs
<!-- Nothing here I mean -->
Thank you for your answer it helps me to understand how does it works.
I am sorry but I did not follow your tutorial exactly (because I was not able to understand what I was supposed to do ;) ).
I edit the rollup.config.js as :
import svelte from 'rollup-plugin-svelte';
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
const production = !process.env.ROLLUP_WATCH;
const BUILD_PATH = '../server/assets';
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: `${BUILD_PATH}/build/bundle.js`
},
plugins: [
svelte({
// enable run-time checks when not in production
dev: !production,
// we'll extract any component CSS out into
// a separate file - better for performance
css: css => {
css.write(`${BUILD_PATH}/build/bundle.css`);
}
}),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
dedupe: ['svelte']
}),
commonjs(),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload(BUILD_PATH),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};
function serve() {
let started = false;
return {
writeBundle() {
if (!started) {
started = true;
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
}
}
};
}
And I move my files is the assets as :
file organization
Then I deleted the homepage.ejs in server/views/pages/
And it works :) !
Thank you again for your quick answer
I usually declare all standard libraries that the application depends on in the manifest under sap.ui5/dependencies/libs.
Now what should I put in the bootstrap argument data-sap-ui-libs, the same libraries? What are the effects if I put less / more in data-sap-ui-libs? How do they differ?
PS. I couldn't find this in SAP's documentation, but please proof me wrong. :-)
The bootstrapping (data-sap-ui-libs) is done in the index.html. It only needs to contain the libs which are referenced in the index.html.
If your code looks like this:
new sap.m.Shell({
app: new sap.ui.core.ComponentContainer({
name: "my.namespace.app",
height: "100%"
})
}).placeAt("content");
Then you should require the following libs:
data-sap-ui-libs="sap.m, sap.ui.core"
If your code looks like this:
sap.ui.require([
"sap/m/Shell",
"sap/ui/core/ComponentContainer"
], function(Shell, ComponentContainer) {
new Shell({
app: new ComponentContainer({
name: "my.namespace.app",
height: "100%"
})
}).placeAt("content");
});
You don't need to require anything (but it may affect loading time of your app).
All libraries that are used in the views should be required in the manifest.json. So if you use sap.m in your app you should require it in your manifest.json, even if you've already required it in the index.html.
This is because the Component.js and the manifest.json are the default entry points for an app and the index.html ist just a wrapper for standalone apps outside of a Fiori Launchpad.
What are the effects if I put less/more in data-sap-ui-libs? How do they differ?
My recommendation is to remove data-sap-ui-libs from index.html altogether. Especially if the app is dealing with OData, it's important to retrieve the $metadata document as early as possible. See the example below:
In index.html
<head>
<script id="sap-ui-bootstrap"
src="https://ui5.sap.com/<version>/resources/sap-ui-core.js"
data-sap-ui-theme="sap_horizon"
data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
data-sap-ui-async="true"
data-sap-ui-compatversion="edge"
data-sap-ui-excludejquerycompat="true"
data-sap-ui-resourceroots='{ "demo": "./" }'
data-sap-ui-xx-waitfortheme="init"
></script><!-- No data-sap-ui-lib -->
</head>
<body id="content" class="sapUiBody">
<div style="height: 100%"
data-sap-ui-component
data-name="demo"
data-height="100%"
></div>
</body>
In manifest.json
{
"sap.app": {
"dataSources": {
"myODataSource": {
"uri": "/odata_org/V2/Northwind/Northwind.svc/",
"type": "OData",
"settings": {
"odataVersion": "2.0",
"localUri": "model/metadata.xml",
"annotations": [
"annotation0"
]
}
},
"annotation0": {
"type": "ODataAnnotation",
"uri": "annotation/annotation0.xml",
"settings": {
"localUri": "annotation/annotation0.xml"
}
}
},
"...": "..."
},
"sap.ui5": {
"dependencies": {
"minUI5Version": "1.108.4",
"libs": {
"sap.ui.core": {},
"sap.m": {},
"sap.ui.table": {},
"sap.ui.unified": {}
}
},
"models": {
"": {
"dataSource": "myODataSource",
"settings": {
"preliminaryContext": true,
"tokenHandling": false
},
"preload": true
}
},
"...": "..."
},
"...": "..."
}
Result
As you can see, the $metadata document is being fetched in parallel with the control libraries. This ensures that entities can be requested right away (e.g. in $batch) as soon as the libs are loaded. If libs were declared in data-sap-ui-libs, they'd be loading first, then the $metadata, and then the entities which creates an unnecessary bottleneck.
But even without considering OData, I noticed the page gets already a bit faster when the libs are removed from data-sap-ui-libs. In general, try different approaches and do performance measurements, in addition to documented performance guidelines, and regardless of what people say (including me).
TL;DR
Use data-sap-ui-libs only if:
The app has no Component.js at all.
Modules from libraries other than sap.ui.core are accessed before creating the component (E.g. instantiating sap.m.Shell as a shell for the ComponentContainer)
Otherwise, remove data-sap-ui-libs altogether and maintain /sap.ui5/dependencies/libs only - Especially if the app is supposed to be launched from an app container such as SAP Fiori launchpad (FLP) which skips loading index.html altogether.
See also What happens if a library preload file / library dependencies is not updated in the UI5-manifest?
I would kept them declared on the manifest.
By declaring them on your .html file under the data-sap-ui-libs, you are basically requiring those dependencies right after the UI5 lib is loaded - even before your component is loaded.
By declaring them on your manifest, you are declaring the dependencies for your own component. So, those dependencies are only loaded before the initialization of your component.
As the component should be isolated, you component should not expect to be always used in a standalone mode.
I have a build.config.xml that has a couple of strings in it like $FABRIC_API_KEY. I want to replace this with process.env.FABRIC_API_KEY in a new file config.xml (build.config.xml should remain the same). I have tried using CopyWebpackPlugin, but I can't seem to get this to do anything.
var CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
...
resolve: {
extensions: ['.ts', '.js', '.json', '.xml'],
...
plugins: [
ionicWebpackFactory.getIonicEnvironmentPlugin(),
new CopyWebpackPlugin([{
from: 'build.config.xml',
to: 'config.xml',
transform: function (content) {
content = content
.replace('$FABRIC_API_SECRET', process.env.FABRIC_API_SECRET)
.replace('$FABRIC_API_KEY', process.env.FABRIC_API_KEY);
return content;
},
}]),
],
};
The file does other things (builds ionic) and everything else works as expected. There are no errors or anything, and config.xml does not get created.
What can I do to copy a file and replace strings in it? I am open to using another plugin.
Probably many things have changed since the OP, but the transform function of the copy-webpack-plugin does allow to modify the file contents.
The content argument passed to the function is a buffer though, hence a simple string replacement can be achieved like this (notice the call to toString()):
new CopyWebpackPlugin([{
from: 'build.config.xml',
to: 'config.xml',
transform(content) {
return content
.toString()
.replace('$FABRIC_API_SECRET', process.env.FABRIC_API_SECRET)
.replace('$FABRIC_API_KEY', process.env.FABRIC_API_KEY);
},
}])
Try with xml-webpack-plugin. I hope this help you.
webpack.config.js
var XMLWebpackPlugin = require('xml-webpack-plugin')
var xmlFiles = [
{
template: path.join(__dirname, 'browserconfig.ejs'),
filename: 'browserconfig.xml',
data: {
square70x70logo: 'images/icon70.png',
square150x150logo: 'images/icon150.png',
wide310x150logo: 'images/icon310x150.png',
square310x310logo: 'images/icon310.png',
tileColor: '#ffffff'
}
}
]
browserconfig.ejs
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="<%= square70x70logo %>"/>
<square150x150logo src="<%= square150x150logo %>"/>
<wide310x150logo src="<%= wide310x150logo %>"/>
<square310x310logo src="<%= square310x310logo %>"/>
<TileColor><%= tileColor %></TileColor>
</tile>
</msapplication>
</browserconfig>
We have an Orchard CMS 1.8 site that has been deployed and the content is now managed by the customer. One thing they are having a problem with is adding Bootstrap UI CSS classes to their content in the Html editor.
For example, they have some content and want to create a link to a "Register Now" page. It's easy enough to create the anchor tag using the toolbar buttons but without knowledge of HTML how would they turn that anchor tag into a Bootstrap button without diving into the HTML.
Also knowing that Bootstrap likes to combine classes like the following, how could a content manager pick a combination of styles from the Html Editor toolbar.
Register Now
Does anyone have a recommendation for customizing TinyMCE to make bootstrap classes more accessible to a content manager?
Thanks,
Brian
In Your Theme; add a ResourceManifest and create a reference to a Javascript file.
manifest.DefineScript("OrchardTinyMce").SetVersion("1.1").SetUrl("orchard-tinymce.js").SetDependencies("TinyMce");
this js file will be a TinyMCE customisation override. Make sure the ScriptName is the same and the version is always higher than the one at use in the TinyMCE module.
var mediaPlugins = ",|";
if (mediaPickerEnabled) {
mediaPlugins += ",mediapicker";
}
if (mediaLibraryEnabled) {
mediaPlugins += ",medialibrary";
}
tinyMCE.init({
theme: "advanced",
schema: "html5",
mode: "specific_textareas",
editor_selector: "tinymce",
plugins: "fullscreen,searchreplace,inlinepopups" + mediaPlugins.substr(2),
theme_advanced_toolbar_location: "top",
theme_advanced_toolbar_align: "left",
theme_advanced_buttons1: "search,replace,|,cut,copy,paste,|,undo,redo" + mediaPlugins + ",|,link,unlink,charmap,emoticon,codeblock,|,bold,italic,|,numlist,bullist,formatselect,blockquote,styleselect,|,code,fullscreen,",
theme_advanced_buttons2: "",
theme_advanced_buttons3: "",
theme_advanced_resizing : true,
convert_urls: false,
content_css: "/Themes/[*YOUR-THEME-NAME*]/Styles/custom.css",
valid_elements: "*[*]",
// shouldn't be needed due to the valid_elements setting, but TinyMCE would strip script.src without it.
extended_valid_elements: "script[type|defer|src|language]"
});
As you can see, now you can customise TinyMCE at will. Take note of the content_css property. That css file will be used in your Editor.
I use it all the time, so my clients can really have a true WYSIWYG experience.
One way to do this is to add bootstrap styles into style_formats in tinymce configuration.
Here is one way to do it by adding to orchard-tinymce.js
style_formats: [
{
title: 'Typography', items: [
{
title: 'Body Copy', items: [
{ title: 'Lead Body Para', block: 'p', classes: 'lead' }
]
},
{
title: 'Inline Text', items: [
{ title: 'Small', inline: 'small' },
{ title: 'Highlight', inline: 'mark' },
{ title: 'Deleted', inline: 'del' },
{ title: 'Strikethrough', inline: 's' },
{ title: 'Insert', inline: 'ins' }
]
},
Complete implementation is here:
https://www.bhavindoshi.com/blog/bootstrap-style-formats-in-tinymce-orchard-or-other-cms