Is there a tool or task runner that can take an HTML document in one language, parse out the content in general/specific HTML tags, run that content through Google translate, then put it back into the markup in the right place in new files? Basically, digest one source file and output multiple variations in different (non-computer) languages.
What I'm hoping for is:
index.html
<!DOCTYPE html>
<html>
<body>
привет мир!
</body>
</html>
Gets compiled to:
en/index.html
<!DOCTYPE html>
<html>
<body>
Hello World!
</body>
</html>
ru/index.html
<!DOCTYPE html>
<html>
<body>
привет мир!
</body>
</html>
ch/index.html
<!DOCTYPE html>
<html>
<body>
你好世界!
</body>
</html>
I obviously don't mind setting up some sort of Gruntfile or whatever that dictates the languages, destinations, etc.
Take a look at get-translation or grunt-google-translate. Also Google Translate has simple REST API, you can write your own plugin from the scratch or use something like grunt-restful.
I was able to piece together a solution using Ruby and Grunt. This could be refactored to be more robust, but it was a working solution, so I ran with it. Keep in mind, the translating script overwrites the source files. Only the Grunt starts making duplicates in new destinations.
Using the easy_translate Rub gem I wrote this script:
#!/usr/bin/ruby
require 'easy_translate'
EasyTranslate.api_key = '' # Get from google
target_path = '' # path to translate
Dir.glob(target_path) do |item|
next if item == '.' or item == '..' or item == '.svn'
contents = ""
update = ""
File.open(item, "r") do |file|
contents += file.read
update += EasyTranslate.translate(contents, :from => :russian, :to => :en)
end
File.open(item, "w"){ }
File.open(item, "w") do |file|
file.write(update)
end
end
Walking through this, each file in the target_path is checked if it’s a worthwhile item we make variables contents and update we’ll use to place in the old and new versions of the contents of the file, respectively. Then we open the file and fill up those variable. On line 20 we empty the file, then in the last block on lines 22-24 we write the update string into the file. I used File.open(item, "w") {} instead of .truncate(0) because I was getting random Unicode characters added to the contents of the file with the latter option. Again, overwriting the files in the translation process is not ideal. It'd be better to make a copy in a new destination, but I didn't do that.
The Ruby script returned a single line of minified HTML and broke Smarty templating, so I used used grunt-prettify and grunt-text-replace to prettify the HTML for ease of use and to make the Smarty stuff work again. The Gruntfile looks like this:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
'prettify': {
options: {
indent: 4,
indent_char: ' ',
wrap_line_length: 0,
brace_style: 'expand',
"unformatted": [
"a",
"code",
"pre"
]
},
all: {
expand: true,
cwd: 'static_ugly',
ext: '.html',
src: ['*.html'],
dest: 'static_pretty'
}
},
'replace': {
fix_smarty: {
src: ['static_pretty/*.html'],
overwrite: true,
replacements: [{
from: '{/ Strip',
to: '{/strip'
},{
from: '{$ This-> setLayout ',
to: '{$this->setLayout'
},{
from: '{$ this- > setPageTitle ',
to: '{$this->setPageTitle'
},{
from: '$ this-> setPageTitle ',
to: '$this->setPageTitle'
},{
from: '{$ smarty.block.footer ',
to: '{$smarty.block.footer'
}]
}
}
});
grunt.loadNpmTasks('grunt-prettify');
grunt.loadNpmTasks('grunt-text-replace');
grunt.registerTask('default', ['prettify', 'replace']);
};
There was a lot more find/replace stuff that I left out since it's project-specific. This solution pretty much does what I wanted in the original question. I did some manual moving around of files in the name of getting it done, but I believe I'll be using a variation of this moving forward and consider it a work in progress.
Related
I fetch data from a MySQL database, the data stored is this:
<p><script>alert('123');</script><br /></p>
When I fetch the data normally I get this as result:
<script>alert('123');</script>
This is fine and works as expected, however when I fetch the data into a textarea which is initialized with Summernote I get an alert like this:
Somehow Summernote converts the escaped html tags to functioning HTML.
How do I fix this?
I have already tried the answer of this question:
Escaped HTML in summernote
It did not work.
Why are you not sanitising data both at the time of storage, and when displayed in the Editor, or outside of the editor? Typically, in my CMS, I don't allow <script/> tags as way to help mitigate users adding potentially dangerous scripts.
That said, there is a PR that is being discussed about how we can best go about fixing this issue. https://github.com/summernote/summernote/pull/3782 information or help would be greatly appreciated to move it along, or even another PR fixing the issue.
I managed to fix it by instead of fetching the data in the textarea fetching it in via jQuery like this:
<textarea name="description" id="description"></textarea>
<script>
$('#description').summernote({
height: 250,
codeviewFilter: false,
codeviewIframeFilter: true,
// toolbar
toolbar: [
['font', ['bold', 'italic', 'underline', 'clear']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['view', ['fullscreen', 'codeview', 'help']]
],
}).on("summernote.enter", function(we, e) {
$(this).summernote('pasteHTML', '<br /> ');
e.preventDefault();
});
$("#description").summernote("code", "<?php echo $video->getDetails('', $fileName, 'desc'); ?>");
</script>
Now it doesn't convert > and $lt; to <> if it is the script tag.
See more information here:
https://github.com/summernote/summernote/pull/3782#issuecomment-774432392
Using javascript you can easily fix this. It worked for me in a React + Django project. I also used django_summer_note and it was also showing data like yours. Then I got that solution:
//simply just create a function like this which will return your data (which one you used with django_summernote).
const createBlog = () => {
return { __html: blog.description };
};
// now in your HTML(JSX) show your data like this.
<div className='' dangerouslySetInnerHTML={createBlog()} />
I want add a css file in only index.html page using if with pug. I have got this code with pug:
- var thepage = { page: './index.html' }
if thepage.page
link(rel="stylesheet", type="text/css", href="../css/slider.min.css")
There are no errors with gulp but it doesn't work.
Try this code below.
It works with the parcel
- var page = location.pathname.split('/').pop();
if (page == '404.pug') {
link(rel="stylesheet", href="css/cli/index.css")
}
else if (page=='index.pug') {
link(rel="stylesheet", href="css/index.css")
}
else {
link(rel="stylesheet", href="css/style.css")
}
Normally pug doesn't get a copy of the request inside the template, it depends on you passing it in from the route. It's pretty easy to add the path though:
res.render('index', { "path": req.path });
Then you can test for the path in your template.
if path === '/'
link(rel="stylesheet", type="text/css", href="../css/slider.min.css")
Given that you only want this rendered in one page it's probably even easier to put a boolean in your res.render for that one page. This also has the added advantage of moving data/decision logic back into the route and leaving the pug template focused only on display logic (a very important factor in writing large pug apps).
res.render('index', { "includeSlider": true });
Then the template can look like this:
if includeSlider
link(rel="stylesheet", type="text/css", href="../css/slider.min.css")
gulp-wrap is an excellent tool allowing me to use template layout to populate HTML files:
gulp.src('/my/project/**/*.html')
.pipe(wrap({ src: '/my/project/layout.tpl' }))
.pipe(gulp.dest('/my/webapp/'));
Now my situation is: for some HTML files (say, files with name containing 'special'), I need to use a different template layout special.tpl. How to incorporate into the workflow above? I have searched but got no result.
Please help, thanks.
Solved the problem by using gulp-switch:
function getLayout(file) {
return file.path.indexOf('special') >= 0 ? 'special' : 'common';
}
return gulp.src(dpwFiles.pages)
.pipe(gulpSwitch(getLayout, {
common: wrap({src: 'layout.tpl' }),
special: wrap({src: 'special.tpl' })
}))
.pipe(gulp.dest('/my/webapp'));
I would like to perform web test and learning like some makes music by sampling. So, I would like to make a new design by compozing with them and add my touch.
Say I have the html, css, js, etc files from the site owner, I imagine it is possible to automatically build templates and layouts as HALM and LESS or SASS files from them. For example, a html parser may find nested common structures in pages. A css parser may find common constants and replace them by variables.
Does such tool already exists ? Or what could be the cavits to develop one ?
Exemple for CSS:
From:
h1 { background-color: #ff14a6; }
h2 { color: #ff14a6; }
To:
$primary: #ff14a6;
h1 { background-color: $primary; }
h2 { color: $primary; }
HTML is formed from: Layout + Template, where Layout is the overall structure of the HTML page. Here is a Ruby example:
File: layout.erb
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> ... etc.
</head>
<body>
<%= yield =>
</body>
</html>
Template replaces layout's yield.
Some layout content is page-specific, while template contains frontmatter. In template (contact.html.erb):
---
title: "Contact Information"
---
In layout (layout.erb):
<title> <%= current_page.data.title %>
</title>
If you want to create a template for whatever information you want to display your best bet is a JSON container to hold the new data and your javascript + jquery to import the data to the html. This could be done with a separate js file for the new data or the same one as the app/web page constructor js file.
This way you could have a set template layout for importing your data and then just change the file if you want to use different data. Alternatively using a framework like knockoutjs or something similar could allow you to do this as well, depending ofc on what you are familiar with or like to use.
The following snippet is a demo of jQuery using data from a JSON object to place data in the HTML (this would be the script.js file):
var view = {
displayStuff: function(obj){
var HTMLwelcomeMsg = '<span class="welcome-message">%data%</span>';
var formattedWelcome = HTMLwelcomeMsg.replace("%data%", obj.welcomeMessage);
$("#header").append(formattedWelcome);
}}
The JSON data can be in a separate file loaded by the JS or the HTML:
var model = {
"dataSample1" : "Some data",
"welcomeMessage" : "Welcome to the sample website",
"dataSample2" : "Some more data",
"someNumbers" : [1,1,253,669],
"moreVars" : {
"someMoreData" : ["123 31st st", "311 2nd st"],
"phoneNums" : ["555-5555", "999-999"]
}
}
Or you can put the data inside the JS file you use to append the elements to the HTML.
Then you call your view from the controller:
var controller = function(){
view.displayStuff(model);
}
and it all just works.
I am making a sort of "html app" which involves a very large number of seperate .html files. The 'app' is a sort of 'pro tips' thing, where on every page, is a life tip. I am wondering if there is a code for opening the next html file within the same directory, instead of changing the next tip's in each html file to open it.
Example:
Next Tip
Then in the next tip's html file I would have to put:
Next Tip
And so on:
Next Tip
Sorry if I am not being clear enough.
If you want a client-side only solution this might work for your scenario. Give the a tag an id and add the script part to very page. It will parse your current filename, parses the number from it, adds one and buildsup the next url, replacing that value on your a tag
<html>
<head>
<script src="nav.js"></script>
</head>
<body>
<!-- REMEMBER TO PUT THE ID ON IT -->
<a id="next" href="n.html">next</a>
</body>
</html>
and create a new file called nav.js in your folder and add this code to it:
window.onload = function() {
var a=document.getElementById('next'),
l=document.location.href,
s=Math.max(l.lastIndexOf('\\'),l.lastIndexOf('/')),
d=l.indexOf('.'),
f=l.substring(s+1,l.indexOf('.')),
p=l.substring(0,s+1),
e=l.substring(s+1+f.length, l.length),
n=parseInt(f,10) + 1;
if (a) {
a.href= p + n.toString()+e;
}
};
You could rename all the files into an ordered way, for example tip1.htm, tip2.htm, etc. with Bulk Rename Utility or Ant Renamer if you don't want to get your hands dirty with lots of CMD and PowerShell. After that, add this php code to your main page:
<?php
$file="";
$counter=0;
$arr=array('tip','0','.htm');
function next_file()
{
$counter=$counter+1;
$arr[1]=streval($counter);
include(join("", $arr));
}
?>
Then just call the next_file() function every time the user clicks on the link.
If you have files 1.html, 2.html, etc. this will work.
On your html pages include a blank div (where you want the link to be):
<div id="link"></div>
Include a separate javascript file in the pages:
<script src="app.js"></script>
And then write this in that javascript file:
window.onload = function() {
var maxPages = 3;
var url = window.location.pathname;
var filename = url.substring(url.lastIndexOf('/')+1);
var thenumber = filename.replace(".html", "");
thenumber++;
if (thenumber > maxPages) {
document.getElementById("link").innerHTML = 'Next Tip';
} else {
document.getElementById("link").innerHTML = 'Next Tip';
}
}
Set maxPages so when you get to the end of all the tips, you will go back to the beginning.