# File lib/asciidoctor/document.rb, line 727
  def save_attributes
    # enable toc and sectnums (i.e., numbered) by default in DocBook backend
    # NOTE the attributes_modified should go away once we have a proper attribute storage & tracking facility
    if (attrs = @attributes)['basebackend'] == 'docbook'
      attrs['toc'] = '' unless attribute_locked?('toc') || @attributes_modified.include?('toc')
      attrs['sectnums'] = '' unless attribute_locked?('sectnums') || @attributes_modified.include?('sectnums')
    end

    unless attrs.key?('doctitle') || !(val = doctitle)
      attrs['doctitle'] = val
    end

    # css-signature cannot be updated after header attributes are processed
    @id = attrs['css-signature'] unless @id

    toc_position_val = if (toc_val = (attrs.delete('toc2') ? 'left' : attrs['toc']))
      # toc-placement allows us to separate position from using fitted slot vs macro
      (toc_placement = attrs.fetch('toc-placement', 'macro')) && toc_placement != 'auto' ? toc_placement : attrs['toc-position']
    else
      nil
    end

    if toc_val && (!toc_val.empty? || !toc_position_val.nil_or_empty?)
      default_toc_position = 'left'
      # TODO rename toc2 to aside-toc
      default_toc_class = 'toc2'
      if !toc_position_val.nil_or_empty?
        position = toc_position_val
      elsif !toc_val.empty?
        position = toc_val
      else
        position = default_toc_position
      end
      attrs['toc'] = ''
      attrs['toc-placement'] = 'auto'
      case position
      when 'left', '<', '&lt;'
        attrs['toc-position'] = 'left'
      when 'right', '>', '&gt;'
        attrs['toc-position'] = 'right'
      when 'top', '^'
        attrs['toc-position'] = 'top'
      when 'bottom', 'v'
        attrs['toc-position'] = 'bottom'
      when 'preamble', 'macro'
        attrs['toc-position'] = 'content'
        attrs['toc-placement'] = position
        default_toc_class = nil
      else
        attrs.delete 'toc-position'
        default_toc_class = nil
      end
      attrs['toc-class'] ||= default_toc_class if default_toc_class
    end

    if (@compat_mode = attrs.key? 'compat-mode')
      attrs['source-language'] = attrs['language'] if attrs.key? 'language'
    end

    # NOTE pin the outfilesuffix after the header is parsed
    @outfilesuffix = attrs['outfilesuffix']

    @header_attributes = attrs.dup

    # unfreeze "flexible" attributes
    unless @parent_document
      FLEXIBLE_ATTRIBUTES.each do |name|
        # turning a flexible attribute off should be permanent
        # (we may need more config if that's not always the case)
        if @attribute_overrides.key?(name) && @attribute_overrides[name]
          @attribute_overrides.delete(name)
        end
      end
    end
  end