diff options
| author | 2021-02-03 19:17:00 -0500 | |
|---|---|---|
| committer | 2021-02-03 19:17:00 -0500 | |
| commit | 3a0d66f07b112b6d2bdc2b57bbf717a89a351ce6 (patch) | |
| tree | a7cf56282e54f05785243bc1e903d6594f2c06ba /nikola/plugins/command/new_post.py | |
| parent | 787b97a4cb24330b36f11297c6d3a7a473a907d0 (diff) | |
New upstream version 8.1.2.upstream/8.1.2
Diffstat (limited to 'nikola/plugins/command/new_post.py')
| -rw-r--r-- | nikola/plugins/command/new_post.py | 140 |
1 files changed, 98 insertions, 42 deletions
diff --git a/nikola/plugins/command/new_post.py b/nikola/plugins/command/new_post.py index f9fe3ff..e6eabbd 100644 --- a/nikola/plugins/command/new_post.py +++ b/nikola/plugins/command/new_post.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2015 Roberto Alsina and others. +# Copyright © 2012-2020 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -26,23 +26,23 @@ """Create a new post.""" -from __future__ import unicode_literals, print_function import io import datetime +import operator import os -import sys +import shutil import subprocess -import operator +import sys -from blinker import signal import dateutil.tz +from blinker import signal from nikola.plugin_categories import Command from nikola import utils COMPILERS_DOC_LINK = 'https://getnikola.com/handbook.html#configuring-other-input-formats' -POSTLOGGER = utils.get_logger('new_post', utils.STDERR_HANDLER) -PAGELOGGER = utils.get_logger('new_page', utils.STDERR_HANDLER) +POSTLOGGER = utils.get_logger('new_post') +PAGELOGGER = utils.get_logger('new_page') LOGGER = POSTLOGGER @@ -89,7 +89,7 @@ def get_date(schedule=False, rule=None, last_date=None, tz=None, iso8601=False): except ImportError: LOGGER.error('To use the --schedule switch of new_post, ' 'you have to install the "dateutil" package.') - rrule = None # NOQA + rrule = None if schedule and rrule and rule: try: rule_ = rrule.rrulestr(rule, dtstart=last_date or date) @@ -110,11 +110,10 @@ def get_date(schedule=False, rule=None, last_date=None, tz=None, iso8601=False): else: tz_str = ' UTC' - return date.strftime('%Y-%m-%d %H:%M:%S') + tz_str + return (date.strftime('%Y-%m-%d %H:%M:%S') + tz_str, date) class CommandNewPost(Command): - """Create a new post.""" name = "new_post" @@ -204,7 +203,14 @@ class CommandNewPost(Command): 'default': '', 'help': 'Import an existing file instead of creating a placeholder' }, - + { + 'name': 'date-path', + 'short': 'd', + 'long': 'date-path', + 'type': bool, + 'default': False, + 'help': 'Create post with date path (eg. year/month/day, see NEW_POST_DATE_PATH_FORMAT in config)' + }, ] def _execute(self, options, args): @@ -234,6 +240,10 @@ class CommandNewPost(Command): twofile = options['twofile'] import_file = options['import'] wants_available = options['available-formats'] + date_path_opt = options['date-path'] + date_path_auto = self.site.config['NEW_POST_DATE_PATH'] and content_type == 'post' + date_path_format = self.site.config['NEW_POST_DATE_PATH_FORMAT'].strip('/') + post_type = options.get('type', 'text') if wants_available: self.print_compilers() @@ -255,16 +265,39 @@ class CommandNewPost(Command): if "@" in content_format: content_format, content_subformat = content_format.split("@") - if not content_format: # Issue #400 + if not content_format and path and not os.path.isdir(path): + # content_format not specified. If path was given, use + # it to guess (Issue #2798) + extension = os.path.splitext(path)[-1] + for compiler, extensions in self.site.config['COMPILERS'].items(): + if extension in extensions: + content_format = compiler + if not content_format: + LOGGER.error("Unknown {0} extension {1}, maybe you need to install a plugin or enable an existing one?".format(content_type, extension)) + return + + elif not content_format and import_file: + # content_format not specified. If import_file was given, use + # it to guess (Issue #2798) + extension = os.path.splitext(import_file)[-1] + for compiler, extensions in self.site.config['COMPILERS'].items(): + if extension in extensions: + content_format = compiler + if not content_format: + LOGGER.error("Unknown {0} extension {1}, maybe you need to install a plugin or enable an existing one?".format(content_type, extension)) + return + + elif not content_format: # Issue #400 content_format = get_default_compiler( is_post, self.site.config['COMPILERS'], self.site.config['post_pages']) - if content_format not in compiler_names: - LOGGER.error("Unknown {0} format {1}, maybe you need to install a plugin?".format(content_type, content_format)) + elif content_format not in compiler_names: + LOGGER.error("Unknown {0} format {1}, maybe you need to install a plugin or enable an existing one?".format(content_type, content_format)) self.print_compilers() return + compiler_plugin = self.site.plugin_manager.getPluginByName( content_format, "PageCompiler").plugin_object @@ -286,7 +319,7 @@ class CommandNewPost(Command): while not title: title = utils.ask('Title') - if isinstance(title, utils.bytes_str): + if isinstance(title, bytes): try: title = title.decode(sys.stdin.encoding) except (AttributeError, TypeError): # for tests @@ -294,28 +327,36 @@ class CommandNewPost(Command): title = title.strip() if not path: - slug = utils.slugify(title) + slug = utils.slugify(title, lang=self.site.default_lang) else: - if isinstance(path, utils.bytes_str): + if isinstance(path, bytes): try: path = path.decode(sys.stdin.encoding) except (AttributeError, TypeError): # for tests path = path.decode('utf-8') - slug = utils.slugify(os.path.splitext(os.path.basename(path))[0]) + if os.path.isdir(path): + # If the user provides a directory, add the file name generated from title (Issue #2651) + slug = utils.slugify(title, lang=self.site.default_lang) + pattern = os.path.basename(entry[0]) + suffix = pattern[1:] + path = os.path.join(path, slug + suffix) + else: + slug = utils.slugify(os.path.splitext(os.path.basename(path))[0], lang=self.site.default_lang) - if isinstance(author, utils.bytes_str): - try: - author = author.decode(sys.stdin.encoding) - except (AttributeError, TypeError): # for tests - author = author.decode('utf-8') + if isinstance(author, bytes): + try: + author = author.decode(sys.stdin.encoding) + except (AttributeError, TypeError): # for tests + author = author.decode('utf-8') # Calculate the date to use for the content - schedule = options['schedule'] or self.site.config['SCHEDULE_ALL'] + # SCHEDULE_ALL is post-only (Issue #2921) + schedule = options['schedule'] or (self.site.config['SCHEDULE_ALL'] and is_post) rule = self.site.config['SCHEDULE_RULE'] self.site.scan_posts() timeline = self.site.timeline last_date = None if not timeline else timeline[0].date - date = get_date(schedule, rule, last_date, self.site.tzinfo, self.site.config['FORCE_ISO8601']) + date, dateobj = get_date(schedule, rule, last_date, self.site.tzinfo, self.site.config['FORCE_ISO8601']) data = { 'title': title, 'slug': slug, @@ -323,16 +364,23 @@ class CommandNewPost(Command): 'tags': tags, 'link': '', 'description': '', - 'type': 'text', + 'type': post_type, } - output_path = os.path.dirname(entry[0]) - meta_path = os.path.join(output_path, slug + ".meta") - pattern = os.path.basename(entry[0]) - suffix = pattern[1:] + if not path: + pattern = os.path.basename(entry[0]) + suffix = pattern[1:] + output_path = os.path.dirname(entry[0]) + if date_path_auto or date_path_opt: + output_path += os.sep + dateobj.strftime(date_path_format) + txt_path = os.path.join(output_path, slug + suffix) + meta_path = os.path.join(output_path, slug + ".meta") else: + if date_path_opt: + LOGGER.warning("A path has been specified, ignoring -d") txt_path = os.path.join(self.site.original_cwd, path) + meta_path = os.path.splitext(txt_path)[0] + ".meta" if (not onefile and os.path.isfile(meta_path)) or \ os.path.isfile(txt_path): @@ -344,6 +392,9 @@ class CommandNewPost(Command): signal('existing_' + content_type).send(self, **event) LOGGER.error("The title already exists!") + LOGGER.info("Existing {0}'s text is at: {1}".format(content_type, txt_path)) + if not onefile: + LOGGER.info("Existing {0}'s metadata is at: {1}".format(content_type, meta_path)) return 8 d_name = os.path.dirname(txt_path) @@ -354,33 +405,38 @@ class CommandNewPost(Command): metadata.update(self.site.config['ADDITIONAL_METADATA']) data.update(metadata) - # ipynb plugin needs the ipython kernel info. We get the kernel name + # ipynb plugin needs the Jupyter kernel info. We get the kernel name # from the content_subformat and pass it to the compiler in the metadata if content_format == "ipynb" and content_subformat is not None: - metadata["ipython_kernel"] = content_subformat + metadata["jupyter_kernel"] = content_subformat # Override onefile if not really supported. if not compiler_plugin.supports_onefile and onefile: onefile = False - LOGGER.warn('This compiler does not support one-file posts.') + LOGGER.warning('This compiler does not support one-file posts.') - if import_file: - with io.open(import_file, 'r', encoding='utf-8') as fh: + if onefile and import_file: + with io.open(import_file, 'r', encoding='utf-8-sig') as fh: content = fh.read() - else: + elif not import_file: if is_page: content = self.site.MESSAGES[self.site.default_lang]["Write your page here."] else: content = self.site.MESSAGES[self.site.default_lang]["Write your post here."] - compiler_plugin.create_post( - txt_path, content=content, onefile=onefile, title=title, - slug=slug, date=date, tags=tags, is_page=is_page, **metadata) + + if (not onefile) and import_file: + # Two-file posts are copied on import (Issue #2380) + shutil.copy(import_file, txt_path) + else: + compiler_plugin.create_post( + txt_path, content=content, onefile=onefile, title=title, + slug=slug, date=date, tags=tags, is_page=is_page, type=post_type, **metadata) event = dict(path=txt_path) if not onefile: # write metadata file with io.open(meta_path, "w+", encoding="utf8") as fd: - fd.write(utils.write_metadata(data)) + fd.write(utils.write_metadata(data, comment_wrap=False, site=self.site)) LOGGER.info("Your {0}'s metadata is at: {1}".format(content_type, meta_path)) event['meta_path'] = meta_path LOGGER.info("Your {0}'s text is at: {1}".format(content_type, txt_path)) @@ -395,7 +451,7 @@ class CommandNewPost(Command): if editor: subprocess.call(to_run) else: - LOGGER.error('$EDITOR not set, cannot edit the post. Please do it manually.') + LOGGER.error('The $EDITOR environment variable is not set, cannot edit the post with \'-e\'. Please edit the post manually.') def filter_post_pages(self, compiler, is_post): """Return the correct entry from post_pages. @@ -512,6 +568,6 @@ class CommandNewPost(Command): More compilers are available in the Plugins Index. Compilers marked with ! and ~ require additional configuration: - ! not in the PAGES/POSTS tuples (unused) + ! not in the POSTS/PAGES tuples and any post scanners (unused) ~ not in the COMPILERS dict (disabled) Read more: {0}""".format(COMPILERS_DOC_LINK)) |
