sitegen.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import argparse
  2. from jinja2 import Environment, FileSystemLoader, contextfilter
  3. from pathlib import Path
  4. from os import walk, makedirs
  5. from os.path import join, exists, splitext, split
  6. from shutil import rmtree, copy, copytree
  7. from functools import lru_cache
  8. LANGUAGES = 'languages'
  9. DEFAULT_LANG = 'en'
  10. REGISTERED_LANG = set()
  11. @lru_cache(None)
  12. def get_lang_dic(lang):
  13. if not exists(LANGUAGES):
  14. makedirs(LANGUAGES)
  15. lang_file = join(LANGUAGES, lang + '.txt')
  16. if not exists(lang_file):
  17. return {}
  18. else:
  19. dic = {}
  20. with open(lang_file) as f:
  21. for line in f.readlines():
  22. key, value = line.strip('\n').split(':')
  23. dic[key] = value
  24. return dic
  25. def save_dic(lang, dic):
  26. with open(join(LANGUAGES, lang + '.txt'), 'w') as f:
  27. for key, value in dic.items():
  28. f.write(f"{key}:{value}\n")
  29. @contextfilter
  30. def lang(ctx, value):
  31. lang = ctx.environment.globals['lang']
  32. if lang == DEFAULT_LANG:
  33. return value
  34. else:
  35. dic = get_lang_dic(lang)
  36. if value in dic and dic[value]:
  37. return dic[value]
  38. else:
  39. dic[value] = ""
  40. save_dic(lang, dic)
  41. print(f"Not translated phrase: `{value}`")
  42. return value
  43. @contextfilter
  44. def lang_url(ctx, value):
  45. name, _ = splitext(ctx.name)
  46. if name.startswith('./'):
  47. name = name[2:]
  48. if value == DEFAULT_LANG:
  49. return "/" + name
  50. else:
  51. REGISTERED_LANG.add(value)
  52. return "/" + value + '/' + name
  53. def static(value):
  54. return f"/static/{value}"
  55. def compile(env, path, target):
  56. lang = env.globals['lang']
  57. for base, _, docs in walk(path):
  58. cur_base = Path(base)
  59. cur_base = Path(*cur_base.parts[1:])
  60. for doc in docs:
  61. if doc.startswith('_'):
  62. # Ignore this files
  63. continue
  64. src = join(base, doc)
  65. if args.with_index and doc != 'index.html':
  66. name, _ = splitext(doc)
  67. dst = join(cur_base, name, 'index.html')
  68. else:
  69. dst = join(cur_base, doc)
  70. if lang != DEFAULT_LANG:
  71. dst = join(lang, dst)
  72. dst = join(target, dst)
  73. dst_folder, _ = split(dst)
  74. if not exists(dst_folder):
  75. makedirs(dst_folder)
  76. template = env.get_template(join(cur_base, doc))
  77. output = template.render()
  78. with open(dst, 'w') as f:
  79. f.write(output)
  80. def run(args):
  81. # Load layout
  82. file_loader = FileSystemLoader(args.source)
  83. env = Environment(loader=file_loader)
  84. env.globals['lang'] = DEFAULT_LANG
  85. # Add filters
  86. env.filters['lang'] = lang
  87. env.filters['lang_url'] = lang_url
  88. env.filters['static'] = static
  89. path = Path(args.source)
  90. if exists(args.target):
  91. rmtree(args.target)
  92. makedirs(args.target)
  93. compile(env, path, args.target)
  94. copytree('static', join(args.target, 'static'))
  95. for other_lang in REGISTERED_LANG:
  96. env.globals['lang'] = other_lang
  97. compile(env, path, args.target)
  98. if __name__ == '__main__':
  99. parser = argparse.ArgumentParser("Site generator")
  100. parser.add_argument('--with_index', action='store_true', default=False)
  101. parser.add_argument('--source', default='layout')
  102. parser.add_argument('--target', default='build')
  103. args = parser.parse_args()
  104. run(args)