diff --git a/includes/media.filter.inc b/includes/media.filter.inc
index b3fa33b..495331e 100644
--- a/includes/media.filter.inc
+++ b/includes/media.filter.inc
@@ -251,6 +251,7 @@ function media_parse_css_declarations($declarations) {
  */
 function media_token_to_markup($match, $wysiwyg = FALSE) {
   $settings = array();
+
   $match = str_replace("[[", "", $match);
   $match = str_replace("]]", "", $match);
   $tag = $match[0];
@@ -326,7 +327,6 @@ function media_token_to_markup($match, $wysiwyg = FALSE) {
     $settings['fields'] = $fields;
 
     if (!empty($tag_info['attributes']) && is_array($tag_info['attributes'])) {
-      $attribute_whitelist = variable_get('media__wysiwyg_allowed_attributes', array('height', 'width', 'hspace', 'vspace', 'border', 'align', 'style', 'class', 'id', 'usemap', 'data-picture-group', 'data-picture-align'));
       $settings['attributes'] = array_intersect_key($tag_info['attributes'], array_flip($attribute_whitelist));
       $settings['fields'] = $fields;
 
@@ -387,6 +387,7 @@ function media_token_to_markup($match, $wysiwyg = FALSE) {
     // Display the field elements.
     $element = array();
     $element['content']['file'] = media_get_file_without_label($file, $tag_info['view_mode'], $settings);
+
     // Overwrite or set the file #alt attribute if it has been set in this
     // instance.
     if (!empty($element['content']['file']['#attributes']['alt'])) {
@@ -400,6 +401,7 @@ function media_token_to_markup($match, $wysiwyg = FALSE) {
     field_attach_prepare_view('file', array($file->fid => $file), $tag_info['view_mode']);
     entity_prepare_view('file', array($file->fid => $file));
     $element['content'] += field_attach_view('file', $file, $tag_info['view_mode']);
+
     if (count(element_children($element['content'])) > 1) {
       // Add surrounding divs to group them together.
       // We dont want divs when there are no additional fields to allow files
@@ -412,6 +414,7 @@ function media_token_to_markup($match, $wysiwyg = FALSE) {
       );
     }
   }
+
   drupal_alter('media_token_to_markup', $element, $tag_info, $settings);
   return drupal_render($element);
 }
@@ -676,8 +679,8 @@ function media_get_file_without_label($file, $view_mode, $settings = array()) {
   // support simple formatters that don't do this, set the element attributes to
   // what was requested, but not if the formatter applied its own logic for
   // element attributes.
-  if (!isset($element['#attributes']) && isset($settings['attributes'])) {
-    $element['#attributes'] = $settings['attributes'];
+  if (!isset($element['#item']['attributes']) && isset($settings['attributes'])) {
+    $element['#item']['attributes'] = $settings['attributes'];
 
     // While this function may be called for any file type, images are a common
     // use-case. theme_image() and theme_image_style() require the 'alt'
diff --git a/js/media.filter.js b/js/media.filter.js
index 2e4ceda..551a8c0 100644
--- a/js/media.filter.js
+++ b/js/media.filter.js
@@ -52,20 +52,26 @@
      * @param content
      */
     replacePlaceholderWithToken: function(content) {
-      var tagmap = Drupal.media.filter.ensure_tagmap();
-      var i = 1;
-      for (var macro in tagmap) {
-        var startTag = Drupal.media.filter.getWrapperStart(i), endTag = Drupal.media.filter.getWrapperEnd(i);
-        var startPos = content.indexOf(startTag), endPos = content.indexOf(endTag);
-        if (startPos !== -1 && endPos !== -1) {
-          // If the placeholder wrappers are empty, remove the macro too.
-          if (endPos - startPos - startTag.length === 0) {
-            macro = '';
-          }
-          content = content.substr(0, startPos) + macro + content.substr(endPos + (new String(endTag)).length);
-        }
-        i++;
-      }
+      Drupal.settings.tagmap = [];
+
+      // Convert all xhtml markup to html for cleaner matching/replacing.
+      content = content.replace(/[\s]\/\>/g, '>');
+
+      // Re-build the macros in case any element has changed in the editor.
+      $('.media-element', content).each(function(i, el) {
+        // TODO zero-index wrapper indices.
+        var startTag = Drupal.media.filter.getWrapperStart(i + 1),
+          endTag = Drupal.media.filter.getWrapperEnd(i + 1),
+          macro = Drupal.media.filter.create_macro($(el));
+
+        Drupal.settings.tagmap[macro] = el.outerHTML;
+
+        content = content
+          .replace(el.outerHTML, macro)
+          .replace(startTag, '')
+          .replace(endTag, '');
+      });
+
       return content;
     },
 
@@ -182,7 +188,7 @@
         file_info.attributes = {};
 
         // Extract whitelisted attributes.
-        $.each(Drupal.media.filter.allowed_attributes, function(i, a) {
+        $.each(Drupal.media.filter.allowed_attributes(), function(i, a) {
           if (value = element.attr(a)) {
             file_info.attributes[a] = value;
           }
