Created
November 17, 2016 10:06
-
-
Save KainokiKaede/bee0ab904569658821d565807cdd4220 to your computer and use it in GitHub Desktop.
Markdown - Anki viewer for Pythonista. Obtains a Markdown file from Dropbox, hides *em* and **strong** characters, and reveals when they are pressed. Great for remembering something.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import editor | |
import markdown2 | |
from bs4 import BeautifulSoup | |
import tempfile | |
import webbrowser | |
import os | |
# filename = editor.get_path() | |
filename = os.path.join(tempfile.gettempdir(),'fi.md') | |
js = ''' | |
<script type="text/javascript"> | |
<!-- | |
function toggleBackgroundColor( id ){ | |
if (document . getElementById( id ) . style . backgroundColor == 'white') { | |
document . getElementById( id ) . style . backgroundColor = 'black' | |
} else { | |
document . getElementById( id ) . style . backgroundColor = 'white' | |
} | |
} | |
// --> | |
</script> | |
''' | |
fi = open(filename, encoding='utf-8') | |
soup = BeautifulSoup('<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>'+js+'</head><body>' | |
+ markdown2.markdown(''.join(fi.readlines())) | |
+'</body></html>', "html5lib") | |
for num, tag in enumerate(soup.find_all(['em', 'strong'])): | |
tag['id'] = 'ankihide'+str(num) | |
tag['style'] = "background-color:black;" | |
tag['onClick'] = "toggleBackgroundColor( 'ankihide"+str(num)+"')" | |
filepath = os.path.join(tempfile.gettempdir(),'fo.html') | |
with open(filepath, 'wb') as fo: | |
fo.write(soup.prettify('utf-8')) | |
webbrowser.open('file://'+filepath) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# DROPBOX IMPORT FOR PYTHONISTA 3 | |
# | |
# SETUP INSTRUCTIONS: | |
# | |
# 1. Go to https://www.dropbox.com/developers/apps (log in if necessary) | |
# 2. Select "Create App" | |
# 3. Configure your app: | |
# * Select "Dropbox API" | |
# * Choose whichever access level you prefer ("Full Dropbox" or "App Folder") | |
# * Enter the app name you wish to use for this script. It must be unique across all Dropbox apps. | |
# * Select the account to associate with this app. | |
# * Agree to the terms and conditions and click "Create app" | |
# 4. On the newly-created app's summary page, click the "Generate" | |
# button under "Generated access token" | |
# 5. Copy the generated token and paste it below (replace "YOUR_TOKEN_HERE"). | |
# 6. (optional) Open the "wrench" (actions) menu in Pythonista and add | |
# this script, so you can run it from everywhere in Pythonista. | |
# Notes: | |
# All selected files are downloaded into the root folder of the Pythonista | |
# script library. If a file with the same name already exists, a numeric | |
# suffix is appended automatically. | |
TOKEN = 'TOKEN HERE' | |
import requests | |
import urllib.request, urllib.parse, urllib.error | |
import os | |
import ui | |
import collections | |
import tempfile | |
def list_folder(folder_path='/'): | |
headers = {'Authorization': 'Bearer %s' % (TOKEN,)} | |
r = requests.get('https://api.dropbox.com/1/metadata/dropbox/%s?list=true' % (urllib.parse.quote(folder_path.encode('utf-8')),), headers=headers) | |
result = r.json() | |
return result.get('contents', None) | |
def download_file(path, dest_filename, progress=None): | |
headers = {'Authorization': 'Bearer %s' % (TOKEN,)} | |
url_path = urllib.parse.quote(path.encode('utf-8')) | |
url = 'https://api-content.dropbox.com/1/files/dropbox/%s' % (url_path,) | |
r = requests.get(url, stream=True, headers=headers) | |
dest_path = os.path.join(os.path.expanduser('~/Documents'), dest_filename) | |
# i = 1 | |
# while os.path.exists(dest_path): | |
# base, ext = os.path.splitext(dest_filename) | |
# dest_path = os.path.join(os.path.expanduser('~/Documents'), base + '-' + str(i) + ext) | |
# i += 1 | |
size = r.headers.get('Content-Length', 0) | |
bytes_written = 0 | |
canceled = False | |
with open(dest_path, 'wb') as f: | |
for chunk in r.iter_content(1024*10): | |
f.write(chunk) | |
bytes_written += len(chunk) | |
if int(size) > 0 and isinstance(progress, collections.Callable): | |
p = float(bytes_written) / float(size) | |
should_cancel = progress(p) | |
if should_cancel: | |
canceled = True | |
break | |
if canceled: | |
os.remove(dest_path) | |
class DropboxView (ui.View): | |
def __init__(self, path='/'): | |
tv = ui.TableView() | |
tv.frame = self.bounds | |
tv.flex = 'WH' | |
ds = ui.ListDataSource([]) | |
ds.action = self.item_selected | |
tv.data_source = ds | |
tv.delegate = ds | |
self.tableview = tv | |
self.add_subview(self.tableview) | |
self.name = 'Dropbox' | |
label = ui.Label(frame=self.bounds) | |
label.flex = 'WH' | |
label.background_color = (1, 1, 1, 0.95) | |
label.text = 'Loading...' | |
label.touch_enabled = True | |
label.alignment = ui.ALIGN_CENTER | |
self.path = path | |
self.add_subview(label) | |
self.status_label = label | |
self.canceled = False | |
def will_close(self): | |
self.canceled = True | |
import AnkiMarkdown | |
def item_selected(self, sender): | |
item = sender.items[sender.selected_row] | |
if item.get('is_dir', False): | |
self.status_label.text = 'Loading Folder...' | |
self.status_label.hidden = False | |
self.path = item['path'] | |
self.load_folder() | |
elif item.get('up', False): | |
self.status_label.text = 'Loading Folder...' | |
self.status_label.hidden = False | |
self.path = os.path.split(self.path)[0] | |
self.load_folder() | |
else: | |
path = item.get('path') | |
self.download_file(path) | |
@ui.in_background | |
def download_file(self, path): | |
self.status_label.text = 'Downloading %s...' % (path,) | |
self.status_label.hidden = False | |
# download_file(path, os.path.split(path)[1], self.download_progress) | |
download_file(path, os.path.join(tempfile.gettempdir(), 'fi.md'), self.download_progress) | |
self.status_label.hidden = True | |
self.close() | |
def download_progress(self, p): | |
self.status_label.text = '%i %% Downloaded...' % (p*100,) | |
return self.canceled | |
@ui.in_background | |
def load_folder(self): | |
infos = list_folder(self.path) | |
items = [] | |
if self.path != '/': | |
items.append({'title': '..', 'image': 'ionicons-arrow-up-c-32', 'up': True}) | |
if not infos: | |
import console | |
console.alert('Error', 'Could not load folder. Please check if you entered the access token correctly.', 'OK', hide_cancel_button=True) | |
self.status_label.hidden = True | |
return | |
for info in infos: | |
path = info.get('path') | |
name = os.path.split(path)[1] | |
if name.startswith('.'): | |
continue | |
is_dir = info.get('is_dir', False) | |
item = {'title': name, 'image': 'ionicons-folder-32' if is_dir else 'ionicons-ios7-download-outline-32', 'accessory_type': 'disclosure_indicator' if is_dir else 'none', 'is_dir': is_dir, 'path': info['path']} | |
items.append(item) | |
def c(o1, o2): | |
u_cmp = -1 * cmp(o1.get('up', False), o2.get('up', False)) | |
if u_cmp != 0: | |
return u_cmp | |
d_cmp = -1 * cmp(o1.get('is_dir', False), o2.get('is_dir', False)) | |
if d_cmp == 0: | |
return cmp(o1.get('path', '').lower(), o2.get('path', '').lower()) | |
return d_cmp | |
self.tableview.data_source.items = items | |
self.status_label.hidden = True | |
self.name = self.path | |
root_view = DropboxView() | |
root_view.frame = (0, 0, 500, 500) | |
root_view.present('sheet') | |
root_view.load_folder() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Copied most of the code for GUI from https://gist.github.com/brenankeller/c5d5de505fa20d93702eeead1fbd0be1 . Thank you.