How to stop Kramdown from removing indents in code blocks? - jekyll

When rendering Python codeblocks on my Jekyll site, Kramdown removes all of the indents.
The code:
from sort.AbstractSort import AbstractSort
class BubbleSort(AbstractSort):
#staticmethod
def swap(arr, i, j):
arr[i], arr[j] = arr[j], arr[i]
def _sort(self, arr):
for i in range(len(arr) - 1):
for j in range(len(arr) - 1):
if arr[j] > arr[j + 1]:
BubbleSort.swap(arr, j, j + 1)
return arr
Kramdown render:
Kramdown doesn't have the best documentation and I couldn't find any obvious settings that I should change in _config.yaml of my Jekyll site.
I'm hosting the site on GitHub pages.
If it is not possible, maybe I should change to a different rendered? But then this is also poorly documented and my attempts to switch to GFM had failed.

As Benjamin W. have written, this is due to bad CSS configuration in assets/css/style.css.
To solve the problem, change:
pre code {
...
white-space: pre-line !important;
...
}
to
pre code {
...
white-space: pre !important;
...
}
solves the problem.

Related

Prevent double compilation of c files in cython

I am writing a wrapper over c libriary and this lib has file with almost all functions, let say, all_funcs.c. This file in turn requires compilation of lots of another c files
I have created all_funcs.pyx, where I wraped all functions, but I also want to create a submodule, that has access to functions from all_funcs.c. What works for now is adding all c-files to both Extensions in setup.py, however each c-file compiles twice: first for all_funcs.pyx and second for submodule extension.
Are there any ways to provide common sourse files to each Extension?
Example of current setup.py:
ext_helpers = Extension(name=SRC_DIR + '.wrapper.utils.helpers',
sources=[SRC_DIR + '/wrapper/utils/helpers.pyx'] + source_files_paths,
include_dirs=[SRC_DIR + '/include/'])
ext_all_funcs = Extension(name=SRC_DIR + '.wrapper.all_funcs',
sources=[SRC_DIR + '/wrapper/all_funcs.pyx'] + source_files_paths,
include_dirs=[SRC_DIR + '/include/'])
EXTENSIONS = [
ext_helpers,
ext_all_funcs,
]
if __name__ == "__main__":
setup(
packages=PACKAGES,
zip_safe=False,
name='some_name',
ext_modules=cythonize(EXTENSIONS, language_level=3)
)
source_files_paths - the list with common c source files
Note: this answer only explains how to avoid multiple compilation of c/cpp-files using libraries-argument of setup-function. It doesn't however explain how to avoid possible problems due to ODR-violation - for that see this SO-post.
Adding libraries-argument to setup will trigger build_clib prior to building of ext_modules (when running setup.py build or setup.py install commands), the resulting static library will also be automatically passed to the linker, when extensions are linked.
For your setup.py, this means:
from setuptools import setup, find_packages, Extension
...
#common c files compiled to a static library:
mylib = ('mylib', {'sources': source_files_paths}) # possible further settings
# no common c-files (taken care of in mylib):
ext_helpers = Extension(name=SRC_DIR + '.wrapper.utils.helpers',
sources=[SRC_DIR + '/wrapper/utils/helpers.pyx'],
include_dirs=[SRC_DIR + '/include/'])
# no common c-files (taken care of in mylib):
ext_all_funcs = Extension(name=SRC_DIR + '.wrapper.all_funcs',
sources=[SRC_DIR + '/wrapper/all_funcs.pyx'],
include_dirs=[SRC_DIR + '/include/'])
EXTENSIONS = [
ext_helpers,
ext_all_funcs,
]
if __name__ == "__main__":
setup(
packages=find_packages(where=SRC_DIR),
zip_safe=False,
name='some_name',
ext_modules=cythonize(EXTENSIONS, language_level=3),
# will be build as static libraries and automatically passed to linker:
libraries = [mylib]
)
To build the extensions inplace one should invoke:
python setupy.py build_clib build_ext --inplace
as build_ext alone is not enough: we need the static libraries to build before they can be used in extensions.

Limit kramdown automatic generation of header IDs up to i.e., <h4>

Is it possible to limit kramdown automatic generation of header IDs up to, i.e., ?
More information in docs: https://kramdown.gettalong.org/converter/html.html#auto-ids
To limit kramdown automatic generation of header IDs up to h4, you have two options:
Write you own id in those headers greater than 4:
##### I have a custom id
{: #my_custom_id}
Disable the auto id generation for those headers:
##### I don't have id!
{::options auto_ids="false" /}
There's no built-in functionality for that option, but you can monkey-patch. The source of the conversion method is here: https://github.com/gettalong/kramdown/blob/master/lib/kramdown/converter/html.rb#L125
So you can do something like this:
module Kramdown
module Converter
class Html
def convert_header(el, indent)
attr = el.attr.dup
level = output_header_level(el.options[:level])
if #options[:auto_ids] && !attr['id'] && (level <= 4)
attr['id'] = generate_id(el.options[:raw_text])
end
#toc << [el.options[:level], attr['id'], el.children] if attr['id'] && in_toc?(el)
format_as_block_html("h#{level}", attr, inner(el, indent), indent)
end
end
end
end
The addition of the && (level <= 4) makes it behave the way you desire.

GitHub Pages mangling syntax highlighting after upgrade to Jekyll 3

I use Github Pages for my personal website. They're upgrading from Jekyll 2 to Jekyll 3 and sending deprecation warnings. I complied with their warnings and switched from redcarpet to kramdown and from pygments to rouge. When I build locally (with bundle exec jekyll serve) everything works. But when I push the changes the syntax highlighting gets mangled wherever I have linenos in my code blocks.
This is the code block:
{% highlight python linenos %}
'''
scrape lyrics from vagalume.com.br
(author: thiagomarzagao.com)
'''
import json
import time
import pickle
import requests
from bs4 import BeautifulSoup
# get each genre's URL
basepath = 'http://www.vagalume.com.br'
r = requests.get(basepath + '/browse/style/')
soup = BeautifulSoup(r.text)
genres = [u'Rock']
u'Ax\u00E9',
u'Forr\u00F3',
u'Pagode',
u'Samba',
u'Sertanejo',
u'MPB',
u'Rap']
genre_urls = {}
for genre in genres:
genre_urls[genre] = soup.find('a', class_ = 'eA', text = genre).get('href')
# get each artist's URL, per genre
artist_urls = {e: [] for e in genres}
for genre in genres:
r = requests.get(basepath + genre_urls[genre])
soup = BeautifulSoup(r.text)
counter = 0
for artist in soup.find_all('a', class_ = 'top'):
counter += 1
print 'artist {} \r'.format(counter)
artist_urls[genre].append(basepath + artist.get('href'))
time.sleep(2) # don't reduce the 2-second wait (here or below) or you get errors
# get each lyrics, per genre
api = 'http://api.vagalume.com.br/search.php?musid='
genre_lyrics = {e: {} for e in genres}
for genre in artist_urls:
print len(artist_urls[genre])
counter = 0
artist1 = None
for url in artist_urls[genre]:
success = False
while not success: # foor loop in case your connection flickers
try:
r = requests.get(url)
success = True
except:
time.sleep(2)
soup = BeautifulSoup(r.text)
hrefs = soup.find_all('a')
for href in hrefs:
if href.has_attr('data-song'):
song_id = href['data-song']
print song_id
time.sleep(2)
success = False
while not success:
try:
song_metadata = requests.get(api + song_id).json()
success = True
except:
time.sleep(2)
if 'mus' in song_metadata:
if 'lang' in song_metadata['mus'][0]: # discard if no language info
language = song_metadata['mus'][0]['lang']
if language == 1: # discard if language != Portuguese
if 'text' in song_metadata['mus'][0]: # discard if no lyrics
artist2 = song_metadata['art']['name']
if artist2 != artist1:
if counter > 0:
print artist1.encode('utf-8') # change as needed
genre_lyrics[genre][artist1] = artist_lyrics
artist1 = artist2
artist_lyrics = []
lyrics = song_metadata['mus'][0]['text']
artist_lyrics.append(lyrics)
counter += 1
print 'lyrics {} \r'.format(counter)
# serialize
with open(genre + '.json', mode = 'wb') as fbuffer:
json.dump(genre_lyrics[genre], fbuffer)
{% endhighlight %}
This is what I see locally:
This is what I see on Github Pages:
(Without linenos the syntax highlighting works fine.)
What could be happening?
I think I got it!
Your code block seems to be fine. No problem there.
Make sure you have added this into your _config.yml:
highlighter: rouge
markdown: kramdown
kramdown:
input: GFM
Probably what you're missing is kramdown input: GFM, isn't it?
Well, I tested locally and worked fine. When uploaded to GitHub, worked fine as well. Should work for you too.
Let me know how it goes, ok? :)
UPDATE!
Add this to your stylesheet and check how it goes:
.lineno { width: 35px; }
Looks like it's something about your CSS styles that is breaking the layout! Keep tweaking your CSS and you're gonna be fine!

SublimeText Output Display Finish Time

I have just started using SublimeText 2 and running python scripts on it.
My output display also shows [ Finished in 0.1s ]
I do not want the output display to show this message. Can anyone help me in this regard.
Kindest Regards
Simply add the
"quiet": true
option to your .sublime-build file.
Sure,
Edit this file:
~/Library/Application Support/Sublime Text 2/Packages/Default/exec.py
def finish(self, proc):
if not self.quiet:
elapsed = time.time() - proc.start_time
exit_code = proc.exit_code()
if exit_code == 0 or exit_code == None:
self.append_data(proc, ("[Finished in %.1fs]") % (elapsed))
else:
self.append_data(proc, ("[Finished in %.1fs with exit code %d]") % (elapsed, exit_code))
And to be more specific, comment out if exit_code == 0.... and the following 3 lines.

Some weird problem with Nokogiri's xpath method

doc.xpath('//img') #this will get some results
doc.xpath('//img[#class="productImage"]') #and this gets nothing at all
doc.xpath('//div[#id="someID"]') # and this won't work either
I don't know what went wrong here,I double checked the HTML source,There are plenty of img tag which contains the attribute(class="productImage").
It's like the attribute selector just won't work.
Here is the URL which the HTML source come from.
http://www.amazon.cn/s/ref=nb_sb_ss_i_0_1?__mk_zh_CN=%E4%BA%9A%E9%A9%AC%E9%80%8A%E7%BD%91%E7%AB%99&url=search-alias%3Daps&field-keywords=%E4%B8%93%E5%85%AB&x=0&y=0&sprefix=%E4%B8%93
please do me a favor if you got some spare time.Parse the HTML content like I do see if you can solve this one
The weird thing is if you use open-uri on that page you get a different result than when using something like curl or wget.
However when you change the User-Agent you actually get probably the page you are looking for:
Analysis:
require 'rubygems'
require 'nokogiri'
require 'open-uri'
require 'pp'
URL = 'http://www.amazon.cn/...'
def analyze_html(file)
doc = Nokogiri.HTML(file)
pp doc.xpath('//img').map { |i| i[:class] }.compact.reject(&:empty?)
puts doc.xpath('//div').map { |i| i[:class] }.grep(/productImage/).count
puts doc.xpath('//div[#class="productImage"]//img').count
pp doc.xpath('//div[#class="productImage"]//img').map { |i| i[:src] }
end
puts "Attempt 1:"
analyze_html(open(URL))
puts "Attempt 2:"
analyze_html(open(URL, "User-Agent" => "Wget/1.10.2"))
Output:
Attempt 1:
["default navSprite"]
0
0
[]
Attempt 2:
["default navSprite", "srSprite spr_kindOfSortBtn"]
16
16
["http://ec4.images-amazon.com/images/I/51fOb3ujSjL._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/513UQ1xiaSL._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/41zKxWXb8HL._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/51bj6XXAouL._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/516GBhDTGCL._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/51ADd3HSE6L._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/51CbB-7kotL._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/51%2Bw40Mk51L._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/519Gny1LckL._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/51Dv6DUF-WL._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/51uuy8yHeoL._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/51T0KEjznqL._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/419WTi%2BdjzL._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/51QTg4ZmMmL._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/51l--Pxw9TL._AA115_.jpg",
"http://ec4.images-amazon.com/images/I/51gehW2qUZL._AA115_.jpg"]
Solution:
Use User-Agent: Wget/1.10.2
Use xpath('//div[#class="productImage"]//img')