I'm trying to build a custom yeoman generator and I'm basing if off of the webapp generator from yeoman. I'm need to know how to add certain js and css files if bootstrap is not selected. These files are currently being stored at the same level as my index.html file along with main.css.
I've tested the generator and everything works just fine, I just can't figure out how to add certain files or exclude them if bootstrap is present. Any help is greatly appreciated.
Please ask a question before a down vote. This is the first time I've messed with a custom generator.
Below is my index.js file:
'use strict';
var join = require('path').join;
var yeoman = require('yeoman-generator');
var chalk = require('chalk');
module.exports = yeoman.generators.Base.extend({
constructor: function () {
yeoman.generators.Base.apply(this, arguments);
// setup the test-framework property, Gruntfile template will need this
this.option('test-framework', {
desc: 'Test framework to be invoked',
type: String,
defaults: 'mocha'
});
this.testFramework = this.options['test-framework'];
this.option('coffee', {
desc: 'Use CoffeeScript',
type: Boolean,
defaults: false
});
this.coffee = this.options.coffee;
this.pkg = require('../package.json');
},
askFor: function () {
var done = this.async();
// welcome message
if (!this.options['skip-welcome-message']) {
this.log(require('yosay')());
this.log(chalk.magenta(
'Out of the box I include HTML5 Boilerplate, jQuery, and a ' +
'Gruntfile.js to build your app.'
));
}
var prompts = [{
type: 'checkbox',
name: 'features',
message: 'What more would you like?',
choices: [{
name: 'Bootstrap',
value: 'includeBootstrap',
checked: true
},{
name: 'Sass',
value: 'includeSass',
checked: false
},{
name: 'Modernizr',
value: 'includeModernizr',
checked: false
}]
}, {
when: function (answers) {
return answers && answers.feature &&
answers.features.indexOf('includeSass') !== -1;
},
type: 'confirm',
name: 'libsass',
value: 'includeLibSass',
message: 'Would you like to use libsass? Read up more at \n' +
chalk.green('https://github.com/andrew/node-sass#node-sass'),
default: false
}];
this.prompt(prompts, function (answers) {
var features = answers.features;
function hasFeature(feat) {
return features && features.indexOf(feat) !== -1;
}
this.includeSass = hasFeature('includeSass');
this.includeBootstrap = hasFeature('includeBootstrap');
this.includeModernizr = hasFeature('includeModernizr');
this.includeLibSass = answers.libsass;
this.includeRubySass = !answers.libsass;
done();
}.bind(this));
},
gruntfile: function () {
this.template('Gruntfile.js');
},
packageJSON: function () {
this.template('_package.json', 'package.json');
},
git: function () {
this.template('gitignore', '.gitignore');
this.copy('gitattributes', '.gitattributes');
},
bower: function () {
var bower = {
name: this._.slugify(this.appname),
private: true,
dependencies: {}
};
if (this.includeBootstrap) {
var bs = 'bootstrap' + (this.includeSass ? '-sass-official' : '');
bower.dependencies[bs] = "~3.2.0";
} else {
bower.dependencies.jquery = "~1.11.1";
}
if (this.includeModernizr) {
bower.dependencies.modernizr = "~2.8.2";
}
this.write('bower.json', JSON.stringify(bower, null, 2));
},
jshint: function () {
this.copy('jshintrc', '.jshintrc');
},
editorConfig: function () {
this.copy('editorconfig', '.editorconfig');
},
mainStylesheet: function () {
var css = 'main.' + (this.includeSass ? 's' : '') + 'css';
this.template(css, 'app/styles/' + css);
// Add imod-grid.css
var imod = 'imod-grid.' + 'css';
this.template(imod, 'app/styles/' + imod);
},
writeIndex: function () {
this.indexFile = this.engine(
this.readFileAsString(join(this.sourceRoot(), 'index.html')),
this
);
// wire Bootstrap plugins
if (this.includeBootstrap && !this.includeSass) {
var bs = 'bower_components/bootstrap/js/';
this.indexFile = this.appendFiles({
html: this.indexFile,
fileType: 'js',
optimizedPath: 'scripts/plugins.js',
sourceFileList: [
bs + 'affix.js',
bs + 'alert.js',
bs + 'dropdown.js',
bs + 'tooltip.js',
bs + 'modal.js',
bs + 'transition.js',
bs + 'button.js',
bs + 'popover.js',
bs + 'carousel.js',
bs + 'scrollspy.js',
bs + 'collapse.js',
bs + 'tab.js'
],
searchPath: '.'
});
}
this.indexFile = this.appendFiles({
html: this.indexFile,
fileType: 'js',
optimizedPath: 'scripts/main.js',
sourceFileList: ['scripts/main.js'],
searchPath: ['app', '.tmp']
});
},
app: function () {
this.directory('app');
this.mkdir('app/scripts');
this.mkdir('app/styles');
this.mkdir('app/images');
this.write('app/index.html', this.indexFile);
if (this.coffee) {
this.write(
'app/scripts/main.coffee',
'console.log "\'Allo from CoffeeScript!"'
);
}
else {
this.write('app/scripts/main.js', 'console.log(\'\\\'Allo \\\'Allo!\');');
}
},
install: function () {
this.on('end', function () {
this.invoke(this.options['test-framework'], {
options: {
'skip-message': this.options['skip-install-message'],
'skip-install': this.options['skip-install'],
'coffee': this.options.coffee
}
});
if (!this.options['skip-install']) {
this.installDependencies({
skipMessage: this.options['skip-install-message'],
skipInstall: this.options['skip-install']
});
}
});
}
});
Related
I'm using ckeditor5 balloon block mode in nuxt project.
I have used online builder and downloaded build files , add the build files to my project and importing them into my editor component and using it!
the only problem that I have is that when the page loads ,
I get an error : editor-isreadonly-has-no-setter.
I tried binding v-model to the editor but the value won't be updated!
note : I have used ckeditor5 classic mode identical to the way that I'm using Balloon Block, donno really what's going on!
this is my component :
<template>
<ckeditor
:id="id"
v-bind="$attrs"
:editor="BalloonBlock"
:config="editorConfig"
v-on="$listeners"
/>
</template>
<script>
let BalloonBlock
let CKEditor
if (process.client) {
BalloonBlock = require('#/plugins/ckeditor/ckeditor')
CKEditor = require('#ckeditor/ckeditor5-vue2')
} else {
CKEditor = { component: { template: '<div></div>' } }
}
export default {
name: 'CKEditor',
components: {
ckeditor: CKEditor.component,
},
props: {
fillErr: {
type: Boolean,
default: false,
required: false,
},
minHeight: {
type: String,
default: '350px',
required: false,
},
label: {
type: String,
default: '',
required: false,
},
},
data() {
return {
classicEditor: BalloonBlock,
editorConfig: {
language: 'fa',
contentsLangDirection: 'rtl',
},
editorElement: null,
id: null,
}
},
computed: {
value() {
return this.$attrs.value
},
},
created() {
this.id = this.uuidv4()
},
mounted() {
if (!document.getElementById('editorFaTranslate')) {
const faScript = document.createElement('script')
faScript.setAttribute('charset', 'utf-8')
faScript.setAttribute('type', 'text/js')
faScript.setAttribute('id', 'editorFaTranslate')
faScript.setAttribute(
'src',
require('##/plugins/ckeditor/translations/fa.js')
)
document.head.appendChild(faScript)
}
const intervalId = setInterval(() => {
const ckEditor = document.getElementById(this.id)
if (ckEditor) {
clearInterval(intervalId)
this.editorElement = ckEditor
}
})
},
methods: {
uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
/[xy]/g,
function (c) {
const r = (Math.random() * 16) | 0
const v = c === 'x' ? r : (r & 0x3) | 0x8
return v.toString(16)
}
)
},
insertTextAtTheEnd(text) {
function findCorrectPosition(htmlStr) {
const lastIndexOfHTMLTag = htmlStr.lastIndexOf('</')
const lastUlTag = htmlStr.lastIndexOf('</ul>')
const lastOlTag = htmlStr.lastIndexOf('</ol>')
if (
lastUlTag === lastIndexOfHTMLTag ||
lastOlTag === lastIndexOfHTMLTag
) {
const lastLiTag = htmlStr.lastIndexOf('</li>')
return lastLiTag
}
return lastIndexOfHTMLTag
}
const currentString = this.value
const correctIndex = findCorrectPosition(currentString)
const firstHalf = currentString.substring(0, correctIndex)
const secondHalf = currentString.substring(correctIndex)
const newString = `${firstHalf}${text}${secondHalf}`
this.$emit('input', newString)
},
},
}
</script>
I would welcome any idea!
I added "#ckeditor/ckeditor5-vue2": "github:ckeditor/ckeditor5-vue2", in my dependencies and all of a sudden my problem was gone!
I have an Electron app with 3 windows and each window has a different menu. The menu template code for each menu is quite long and I would like to externalize it. So far nothing I have tried works.
I've tried different ways to "modularize" it but got lots of errors. The approach below works to set up the menu, but none of the functions referenced in the menu work (e.g. quitApplication).
Is what I am trying to do not possible or am I just "doing it wrong"?
var test = require("./app/js/menuTest.js");
var tm = new test();
var menuTemplate = tm.getMenu();
myWindow = Menu.buildFromTemplate(menuTemplate);
menuTest.js
function testMenu() {
this.getMenu = function () {
var menuTemplate = [
{
label: global.productData.appName,
submenu: [
{ label: 'About ' + global.productData.appName, click: () => { showAboutWindow() } },
{ type: 'separator' },
{ role: 'hide' },
{ role: 'hideothers' },
{ role: 'unhide' },
{ type: 'separator' },
{ label: 'Quit', click: () => { quitApplication() }, accelerator: 'CmdOrCtrl+q' }
]
// code deleted for clarity
return menuTemplate;
}
}
module.exports = testMenu;
From how I understand your question, you want to move the template code out of your main process script, but keep the functions in there.
This can be achieved by moving the menu structure object into a separate module. The module exports a function that takes an object with references to the functions you want to call in the menu.
I believe this does not add significant complexity and "externalizes" just the menu template code.
menu1.js:
module.exports = function(actions) {
return [
{
label: "Foo",
submenu: [
{ label: "Bar", click: actions.bar },
{ label: "About", click: actions.about }
]
}
];
}
main.js:
const {app,BrowserWindow,Menu} = require("electron");
const actions = {
bar: function () {
console.log("bar");
},
about: function () {
console.log("about");
}
};
const menu1_template = require("./menu1.js")(actions);
const menu1 = Menu.buildFromTemplate(menu1_template);
Menu.setApplicationMenu(menu1);
let mainWindow;
app.on("ready", function() {
mainWindow = new BrowserWindow();
});
I am trying to extend an Electron-project.
I have a new BrowserWindow (basicly a new tab in a browser) which should contain the Documention. The Documentation is written in markdown so I´s like to know how to open my markdown file in this BrowserWindow...
Basicly I just need a way to convert a markdownfile on runtime to a webpage.
You'll need the node module fs to open the file and there's a js library called marked - look for that in npm. It renders markdown.
Update - here's a minimal electron app example, tested on electron 0.37.8.
//start - package.json:
{
"name": "mini-md-example",
"version": "0.1.0",
"description": "A small Electron application to open/display a markdown file",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron-prebuilt": "^0.37.7",
"marked": "^0.3.5"
}
}
//:end - package.json
//start - main.js:
const electron = require('electron')
// Module to control application life.
const app = electron.app
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow
const fs = require('fs');
var dialog = require('dialog')
var path = require('path')
var defaultMenu = require('./def-menu-main')
var Menu = require('menu')
const {ipcMain} = electron;
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 999, height: 800})
// and load the index.html of the app.
mainWindow.loadURL(`file://${__dirname}/index.html`)
// Open the DevTools.
mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
var OpenFile = function() {
dialog.showOpenDialog(mainWindow, {
filters: [{name: 'Markdown', extensions: ['md', 'markdown']}],
properties: ['openFile']
}, function(paths) {
if (!paths) return false;
var fPath = paths[0];
var fName = path.basename(fPath);
var fData = fs.readFileSync(fPath, 'utf8');
mainWindow.webContents.send('file-open', fPath, fName, fData);
})
}
var SendEvent = function(name) {
return function() {mainWindow.webContents.send(name);};
};
// Get template for default menu
var menu = defaultMenu()
// Add my very own custom FILE menu
menu.splice(0, 0, {
label: 'File',
submenu: [
{
label: 'Open',
accelerator: "CmdOCtrl+O",
click: OpenFile
},
]
})
// Set top-level application menu, using modified template
Menu.setApplicationMenu(Menu.buildFromTemplate(menu));
//:end - main.js
//start - index.html:
<!DOCTYPE html>
<html>
<body>
<div id="content"></div>
<script>
var marked = require('marked')
var ipc = require('electron').ipcRenderer
ipc.on('file-open', function(event, fPath, filename, filedata)
{
document.getElementById('content').innerHTML = marked(filedata) ;
})
</script>
</body>
</html>
//:end - index.html
//start - def-menu-main.js:
var electron = require('electron') // this should work if you're in the electron environment
//var app = electron.remote.app
// original app var calls remote as if this is used in a renderer, but for me menus are a main app thing
var app = electron.app
var shell = electron.shell
module.exports = function() {
var template = [
{
label: 'View',
submenu: [
{
label: 'Reload',
accelerator: 'CmdOrCtrl+R',
click: function(item, focusedWindow) {
if (focusedWindow)
focusedWindow.reload();
}
},
{
label: 'Toggle Full Screen',
accelerator: (function() {
if (process.platform === 'darwin')
return 'Ctrl+Command+F';
else
return 'F11';
})(),
click: function(item, focusedWindow) {
if (focusedWindow)
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
}
},
{
label: 'Toggle Developer Tools',
accelerator: (function() {
if (process.platform === 'darwin')
return 'Alt+Command+I';
else
return 'Ctrl+Shift+I';
})(),
click: function(item, focusedWindow) {
if (focusedWindow)
focusedWindow.toggleDevTools();
}
},
]
},
{
label: 'Window',
role: 'window',
submenu: [
{
label: 'Minimize',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
},
{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
role: 'close'
},
]
},
{
label: 'Help',
role: 'help',
submenu: [
{
label: 'Learn More',
click: function() { shell.openExternal('http://electron.atom.io') }
},
]
},
];
if (process.platform === 'darwin') {
var name = app.getName();
template.unshift({
label: name,
submenu: [
{
label: 'About ' + name,
role: 'about'
},
{
type: 'separator'
},
{
label: 'Services',
role: 'services',
submenu: []
},
{
type: 'separator'
},
{
label: 'Hide ' + name,
accelerator: 'Command+H',
role: 'hide'
},
{
label: 'Hide Others',
accelerator: 'Command+Shift+H',
role: 'hideothers'
},
{
label: 'Show All',
role: 'unhide'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'Command+Q',
click: function() { app.quit(); }
},
]
});
var windowMenu = template.find(function(m) { return m.role === 'window' })
if (windowMenu) {
windowMenu.submenu.push(
{
type: 'separator'
},
{
label: 'Bring All to Front',
role: 'front'
}
);
}
}
return template;
}
//:end - def-menu-main.js
I have this code, I want to go thru all the links available at the bottom of the page. After clicking them I want to make sure the URL opened is the correct one.
I think the the recursive calls are done too early. Another issue is how can I do to tell that link belongs to certain URL.
function links(browser, total_links) {
if (total_links <= 0) {
browser.end();
return;
}
console.log("Number of links: " + total_links);
console.log('Flag1');
browser
.waitForElementVisible('.bottom .socal>span:nth-child(' + total_links + ')', 1000, function () {
console.log('Flag2');
browser.execute('scrollIntoView(alignToBottom)')
.moveToElement('.bottom .socal>span:nth-child(' + total_links + ')', 3, 3)
.pause(3000)
.click('.bottom .socal>span:nth-child(' + total_links + ') a', function () {
console.log('Flag3');
browser.keys(['\uE006'])
// .assert.urlContains('facebook')
//.assert.urlEquals('https://www.facebook.com/unitel.ao/?fref=ts')
.window_handles(function (result) {
console.log('Flag4');
browser.assert.equal(result.value.length, 2, 'There should be two windows open.');
var handle_1 = result.value[0];
var handle_2 = result.value[1];
browser.switchWindow(handle_2, function () {
browser.closeWindow()
.switchWindow(handle_1, function () {
total_links = total_links - 1;
links(browser, total_links);
});
});
});
console.log('Flag5');
});
console.log('Flag6');
});
}
module.exports = {
'Social links': function (browser) {
var total_links;
browser
.url('http://m.unitel.ao/fit/')
.execute(function () {
return document.querySelectorAll("ul.navbar-nav>li").length;
},
function (tags) {
total_links = tags.value;
links(browser, total_links);
});
// .end();
}
};
Humh, it seems like you were stuck with this days ago.I recommend page-object,it will help you stay away hardcode and easier to change css in the future.
A home page object(home.js) may be like this :
module.exports = {
url: function() {
return 'http://m.unitel.ao/fit/';
},
commands: [{
getUrl: function(n) {
if (n === 3) {
return 'youtube.com/user/tvUNITEL';
}
if (n === 1) {
return 'facebook.com/unitel.ao/?fref=ts';
}
if (n === 2) {
return 'instagram.com/unitelangola/';
}
if (n === 4) {
return 'plus.google.com/110849312028181626033/posts';
}
}
}],
elements: {
facebook: {
selector: '.bottom .socal>span:nth-child(1)',
},
instagram: {
selector: '.bottom .socal>span:nth-child(2)'
},
youtube: {
selector: '.bottom .socal>span:nth-child(3)'
},
googleplus: {
selector: '.bottom .socal>span:nth-child(4)'
}
}
};
And in your test should be like :
module.exports = {
'Social links': function(browser) {
const homePage = browser.page.home();
var j = 0;
for (var i in homePage.elements) {
homePage
.navigate()
.waitForElementVisible(homePage.elements[i].selector, 5000, false,
function() {
browser.pause(3000);
})
.click(homePage.elements[i].selector, function() {
browser
.pause(2000)
.window_handles(function(result) {
url = homePage.getUrl(j + 1);
var home = result.value[0];
var handle = result.value[1];
browser
.switchWindow(handle)
.verify.urlContains(url)
.closeWindow()
.switchWindow(home);
j += 1;
});
})
}
}
};
PS:In case you dont know how to create a page-object, here is the doc http://nightwatchjs.org/guide#using-page-objects.
In config file
Nightwatch.js:
"src_folders" : ["tests"],
"output_folder" : "reports",
"custom_commands_path" : "",
"custom_assertions_path" : "",
"page_objects_path" : "./lib/pages", /* you need to add the path,e.g: './lib/pages', */
"globals_path" : "",
I need to have multiple events associated with the fineuploader instantiation, but I'm not sure how to go about it. Can't they be added within the fineuploader properties, etc.? Isn't the complete event then called onComplete? Is there an example that exists? Also, I'm confused about the number of closing brackets, etc. When I originally cut and pasted this code in, there was an extra )}; that sat outside. I removed that, but I'm not sure if that's cool or not for the actual code. Any help is appreciated, as I've been toying with this for hours. Some variables have been set outside this code.
$(document).ready(function () {
var controlType = '#Model.ControlType';
var surveyItemResultId = #Model.Results[0].SurveyItemResultId;
var itemId = #Model.SurveyItemId;
var instance = #Model.Results[0].SurveyInstanceID;
var loopingCounter = 0;
var fineuploader = $('#files-upload').fineUploader({
request:
{
endpoint: '#Url.Action("UploadFile", "Survey")',
customHeaders: { Accept: 'application/json' },
params: {
surveyInstanceId: (function () { return instance; }),
surveyItemResultId: (function () { return surveyItemResultId; }),
itemId: (function () { return itemId; }),
loopingIndex: (function () { return loopingCounter++; })
}
},
validation: {
acceptFiles: ['image/*','application/pdf','text/csv'] ,
allowedExtensions: ['jpeg', 'jpg', 'gif', 'png', 'csv', 'pdf'],
sizeLimit: 1024*1024*1 // 1MB
},
multiple: true,
text: {
uploadButton: '<i class="icon-plus icon-white"></i>Select your upload file(s)'
}
})
.on('complete', function(event, id, fileName, responseJSON) {
alert("Success: " + responseJSON.success);
uploadedFileCounter++;
if (filesToUpload == uploadedFileCounter)
{
alert("DONE UPLOADING!");
}
}).on('submitted', function(event, id, filename) {
filesToUpload++;
alert("submitted: " + filesToUpload);
}
});
});
Your code is littered with syntax and other errors. First off, you are referencing filesToUpload and uploadedFileCounter variables that are not defined anywhere in your code. Second, you have an extra closing bracket in your code.
There are also some formating issues with your code. First, Your code is inconsistently indented. Second, you are mixing placement of curly brackets.
Here is your original code with my adjustments:
$(document).ready(function () {
var controlType = '#Model.ControlType',
surveyItemResultId = #Model.Results[0].SurveyItemResultId,
itemId = #Model.SurveyItemId,
instance = #Model.Results[0].SurveyInstanceID,
loopingCounter = 0,
filesToUpload = 0,
uploadedFileCounter = 0;
var fineuploader = $('#files-upload').fineUploader({
request: {
endpoint: '#Url.Action("UploadFile", "Survey")',
customHeaders: { Accept: 'application/json' },
params: {
surveyInstanceId: (function () { return instance; }),
surveyItemResultId: (function () { return surveyItemResultId; }),
itemId: (function () { return itemId; }),
loopingIndex: (function () { return loopingCounter++; })
}
},
validation: {
acceptFiles: ['image/*','application/pdf','text/csv'] ,
allowedExtensions: ['jpeg', 'jpg', 'gif', 'png', 'csv', 'pdf'],
sizeLimit: 1024*1024*1 // 1MB
},
multiple: true,
text: {
uploadButton: '<i class="icon-plus icon-white"></i>Select your upload file(s)'
}
})
.on('complete', function(event, id, fileName, responseJSON) {
alert("Success: " + responseJSON.success);
uploadedFileCounter++;
if (filesToUpload == uploadedFileCounter) {
alert("DONE UPLOADING!");
}
}).on('submitted', function(event, id, filename) {
filesToUpload++;
alert("submitted: " + filesToUpload);
});
});