sitegen.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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 name == 'index':
  49. name = ''
  50. if value == DEFAULT_LANG:
  51. return "/" + name
  52. else:
  53. REGISTERED_LANG.add(value)
  54. return "/" + value + '/' + name
  55. def static(value):
  56. return f"/static/{value}"
  57. def compile(env, path, target):
  58. lang = env.globals['lang']
  59. for base, _, docs in walk(path):
  60. cur_base = Path(base)
  61. cur_base = Path(*cur_base.parts[1:])
  62. for doc in docs:
  63. if doc.startswith('_'):
  64. # Ignore this files
  65. continue
  66. src = join(base, doc)
  67. if args.with_index and doc != 'index.html':
  68. name, _ = splitext(doc)
  69. dst = join(cur_base, name, 'index.html')
  70. else:
  71. dst = join(cur_base, doc)
  72. if lang != DEFAULT_LANG:
  73. dst = join(lang, dst)
  74. dst = join(target, dst)
  75. dst_folder, _ = split(dst)
  76. if not exists(dst_folder):
  77. makedirs(dst_folder)
  78. template = env.get_template(join(cur_base, doc))
  79. output = template.render()
  80. with open(dst, 'w') as f:
  81. f.write(output)
  82. def run(args):
  83. # Load layout
  84. file_loader = FileSystemLoader(args.source)
  85. env = Environment(loader=file_loader)
  86. env.globals['lang'] = DEFAULT_LANG
  87. # Add filters
  88. env.filters['lang'] = lang
  89. env.filters['lang_url'] = lang_url
  90. env.filters['static'] = static
  91. path = Path(args.source)
  92. if exists(args.target):
  93. rmtree(args.target)
  94. if exists('root'):
  95. copytree('root', args.target)
  96. else:
  97. makedirs(args.target)
  98. compile(env, path, args.target)
  99. copytree('static', join(args.target, 'static'))
  100. for other_lang in REGISTERED_LANG:
  101. env.globals['lang'] = other_lang
  102. compile(env, path, args.target)
  103. if __name__ == '__main__':
  104. parser = argparse.ArgumentParser("Site generator")
  105. parser.add_argument('--with_index', action='store_true', default=False)
  106. parser.add_argument('--source', default='layout')
  107. parser.add_argument('--target', default='build')
  108. args = parser.parse_args()
  109. run(args)